From 9d4022b833aa6a2595ec455b10305c29ea1a2c23 Mon Sep 17 00:00:00 2001 From: Elliot Nunn Date: Sat, 20 Jun 2020 09:33:04 +0800 Subject: [PATCH] Initial commit, including vasm --- .gitignore | 3 + NetBoot.py | 39 + README.md | 28 + bbraun-pram/NBPRAM.c | 1 + bbraun-pram/pram.c | 7 + bbraun-pram/pramtest | 0 bbraun-pram/pramtest.SYM | Bin 0 -> 110592 bytes bbraun-pram/pramtest.proj | Bin 0 -> 4279 bytes vasm-1/Makefile | 18 + vasm-1/Makefile.68k | 18 + vasm-1/Makefile.Cygwin | 18 + vasm-1/Makefile.Haiku | 18 + vasm-1/Makefile.MOS | 18 + vasm-1/Makefile.MiNT | 18 + vasm-1/Makefile.OS4 | 18 + vasm-1/Makefile.PUp | 18 + vasm-1/Makefile.TOS | 18 + vasm-1/Makefile.WOS | 18 + vasm-1/Makefile.Win32 | 30 + vasm-1/Makefile.Win32FromLinux | 22 + vasm-1/atom.c | 672 +++ vasm-1/atom.h | 152 + vasm-1/cond.c | 85 + vasm-1/cond.h | 25 + vasm-1/cpus/6502/cpu.c | 588 +++ vasm-1/cpus/6502/cpu.h | 96 + vasm-1/cpus/6502/cpu_errors.h | 9 + vasm-1/cpus/6502/opcodes.h | 287 ++ vasm-1/cpus/6800/cpu.c | 398 ++ vasm-1/cpus/6800/cpu.h | 80 + vasm-1/cpus/6800/cpu_errors.h | 3 + vasm-1/cpus/6800/opcodes.h | 339 ++ vasm-1/cpus/arm/cpu.c | 1751 +++++++ vasm-1/cpus/arm/cpu.h | 214 + vasm-1/cpus/arm/cpu_errors.h | 31 + vasm-1/cpus/arm/opcodes.h | 201 + vasm-1/cpus/c16x/cpu.c | 786 ++++ vasm-1/cpus/c16x/cpu.h | 88 + vasm-1/cpus/c16x/cpu_errors.h | 8 + vasm-1/cpus/c16x/opcodes.h | 233 + vasm-1/cpus/jagrisc/cpu.c | 616 +++ vasm-1/cpus/jagrisc/cpu.h | 86 + vasm-1/cpus/jagrisc/cpu_errors.h | 3 + vasm-1/cpus/jagrisc/opcodes.h | 72 + vasm-1/cpus/m68k/cpu.c | 6003 ++++++++++++++++++++++++ vasm-1/cpus/m68k/cpu.h | 441 ++ vasm-1/cpus/m68k/cpu_errors.h | 72 + vasm-1/cpus/m68k/cpu_models.h | 129 + vasm-1/cpus/m68k/opcodes.h | 2273 +++++++++ vasm-1/cpus/m68k/operands.h | 631 +++ vasm-1/cpus/m68k/specregs.h | 151 + vasm-1/cpus/ppc/cpu.c | 913 ++++ vasm-1/cpus/ppc/cpu.h | 264 ++ vasm-1/cpus/ppc/cpu_errors.h | 17 + vasm-1/cpus/ppc/opcodes.h | 2511 ++++++++++ vasm-1/cpus/ppc/operands.h | 587 +++ vasm-1/cpus/qnice/cpu.c | 302 ++ vasm-1/cpus/qnice/cpu.h | 58 + vasm-1/cpus/qnice/cpu_errors.h | 6 + vasm-1/cpus/qnice/opcodes.h | 18 + vasm-1/cpus/test/cpu.c | 306 ++ vasm-1/cpus/test/cpu.h | 55 + vasm-1/cpus/test/cpu_errors.h | 3 + vasm-1/cpus/tr3200/cpu.c | 524 +++ vasm-1/cpus/tr3200/cpu.h | 48 + vasm-1/cpus/tr3200/cpu_errors.h | 3 + vasm-1/cpus/tr3200/opcodes.h | 150 + vasm-1/cpus/vidcore/cpu.c | 1206 +++++ vasm-1/cpus/vidcore/cpu.h | 142 + vasm-1/cpus/vidcore/cpu_errors.h | 5 + vasm-1/cpus/vidcore/opcodes.h | 1041 ++++ vasm-1/cpus/x86/cpu.c | 1957 ++++++++ vasm-1/cpus/x86/cpu.h | 269 ++ vasm-1/cpus/x86/cpu_errors.h | 26 + vasm-1/cpus/x86/opcodes.h | 1062 +++++ vasm-1/cpus/x86/registers.h | 180 + vasm-1/cpus/z80/cpu.c | 2265 +++++++++ vasm-1/cpus/z80/cpu.h | 273 ++ vasm-1/cpus/z80/cpu_errors.h | 27 + vasm-1/doc/cpu_6502.texi | 131 + vasm-1/doc/cpu_6800.texi | 85 + vasm-1/doc/cpu_arm.texi | 248 + vasm-1/doc/cpu_c16x.texi | 124 + vasm-1/doc/cpu_jagrisc.texi | 124 + vasm-1/doc/cpu_m68k.texi | 1090 +++++ vasm-1/doc/cpu_ppc.texi | 172 + vasm-1/doc/cpu_tr3200.texi | 127 + vasm-1/doc/cpu_x86.texi | 168 + vasm-1/doc/cpu_z80.texi | 165 + vasm-1/doc/interface.texi | 1458 ++++++ vasm-1/doc/output_aout.texi | 62 + vasm-1/doc/output_bin.texi | 49 + vasm-1/doc/output_elf.texi | 59 + vasm-1/doc/output_hunk.texi | 115 + vasm-1/doc/output_srec.texi | 54 + vasm-1/doc/output_test.texi | 38 + vasm-1/doc/output_tos.texi | 54 + vasm-1/doc/output_vobj.texi | 38 + vasm-1/doc/output_xfile.texi | 49 + vasm-1/doc/syntax_madmac.texi | 330 ++ vasm-1/doc/syntax_mot.texi | 804 ++++ vasm-1/doc/syntax_oldstyle.texi | 640 +++ vasm-1/doc/syntax_std.texi | 545 +++ vasm-1/doc/vasm.texi | 187 + vasm-1/doc/vasm_main.texi | 484 ++ vasm-1/dwarf.c | 488 ++ vasm-1/dwarf.h | 65 + vasm-1/elf_reloc_386.h | 77 + vasm-1/elf_reloc_68k.h | 108 + vasm-1/elf_reloc_arm.h | 96 + vasm-1/elf_reloc_jag.h | 86 + vasm-1/elf_reloc_ppc.h | 276 ++ vasm-1/elf_reloc_x86_64.h | 90 + vasm-1/error.c | 292 ++ vasm-1/error.h | 25 + vasm-1/expr.c | 1440 ++++++ vasm-1/expr.h | 65 + vasm-1/general_errors.h | 75 + vasm-1/history | 1394 ++++++ vasm-1/hugeint.c | 534 +++ vasm-1/hugeint.h | 45 + vasm-1/make.rules | 121 + vasm-1/obj/.dummy | 0 vasm-1/obj/m68k_std_atom.o | Bin 0 -> 12500 bytes vasm-1/obj/m68k_std_cond.o | Bin 0 -> 2252 bytes vasm-1/obj/m68k_std_cpu.o | Bin 0 -> 263144 bytes vasm-1/obj/m68k_std_dwarf.o | Bin 0 -> 7856 bytes vasm-1/obj/m68k_std_error.o | Bin 0 -> 17368 bytes vasm-1/obj/m68k_std_expr.o | Bin 0 -> 22984 bytes vasm-1/obj/m68k_std_hugeint.o | Bin 0 -> 8016 bytes vasm-1/obj/m68k_std_osdep.o | Bin 0 -> 1960 bytes vasm-1/obj/m68k_std_output_aout.o | Bin 0 -> 10312 bytes vasm-1/obj/m68k_std_output_bin.o | Bin 0 -> 2724 bytes vasm-1/obj/m68k_std_output_elf.o | Bin 0 -> 17256 bytes vasm-1/obj/m68k_std_output_hunk.o | Bin 0 -> 13480 bytes vasm-1/obj/m68k_std_output_srec.o | Bin 0 -> 5668 bytes vasm-1/obj/m68k_std_output_test.o | Bin 0 -> 1412 bytes vasm-1/obj/m68k_std_output_tos.o | Bin 0 -> 6920 bytes vasm-1/obj/m68k_std_output_vobj.o | Bin 0 -> 5960 bytes vasm-1/obj/m68k_std_output_xfile.o | Bin 0 -> 6044 bytes vasm-1/obj/m68k_std_parse.o | Bin 0 -> 20984 bytes vasm-1/obj/m68k_std_reloc.o | Bin 0 -> 3200 bytes vasm-1/obj/m68k_std_supp.o | Bin 0 -> 14444 bytes vasm-1/obj/m68k_std_symbol.o | Bin 0 -> 10404 bytes vasm-1/obj/m68k_std_symtab.o | Bin 0 -> 4700 bytes vasm-1/obj/m68k_std_syntax.o | Bin 0 -> 44388 bytes vasm-1/obj/m68k_std_vasm.o | Bin 0 -> 29336 bytes vasm-1/obj/vobjdump.o | Bin 0 -> 12484 bytes vasm-1/osdep.c | 206 + vasm-1/osdep.h | 14 + vasm-1/output_aout.c | 636 +++ vasm-1/output_aout.h | 133 + vasm-1/output_bin.c | 141 + vasm-1/output_elf.c | 906 ++++ vasm-1/output_elf.h | 319 ++ vasm-1/output_errors.h | 14 + vasm-1/output_hunk.c | 1060 +++++ vasm-1/output_hunk.h | 97 + vasm-1/output_srec.c | 394 ++ vasm-1/output_test.c | 34 + vasm-1/output_tos.c | 383 ++ vasm-1/output_tos.h | 40 + vasm-1/output_vobj.c | 293 ++ vasm-1/output_xfile.c | 360 ++ vasm-1/output_xfile.h | 36 + vasm-1/parse.c | 1240 +++++ vasm-1/parse.h | 102 + vasm-1/reloc.c | 152 + vasm-1/reloc.h | 67 + vasm-1/stabs.h | 98 + vasm-1/supp.c | 705 +++ vasm-1/supp.h | 80 + vasm-1/symbol.c | 485 ++ vasm-1/symbol.h | 100 + vasm-1/symtab.c | 155 + vasm-1/symtab.h | 33 + vasm-1/syntax/madmac/syntax.c | 1059 +++++ vasm-1/syntax/madmac/syntax.h | 14 + vasm-1/syntax/madmac/syntax_errors.h | 13 + vasm-1/syntax/mot/syntax.c | 2631 +++++++++++ vasm-1/syntax/mot/syntax.h | 40 + vasm-1/syntax/mot/syntax_errors.h | 25 + vasm-1/syntax/oldstyle/syntax.c | 1794 +++++++ vasm-1/syntax/oldstyle/syntax.h | 31 + vasm-1/syntax/oldstyle/syntax_errors.h | 25 + vasm-1/syntax/std/syntax.c | 1473 ++++++ vasm-1/syntax/std/syntax.h | 28 + vasm-1/syntax/std/syntax_errors.h | 24 + vasm-1/syntax/test/syntax.c | 437 ++ vasm-1/syntax/test/syntax.h | 11 + vasm-1/syntax/test/syntax_errors.h | 13 + vasm-1/tfloat.h | 10 + vasm-1/vasm.c | 1705 +++++++ vasm-1/vasm.h | 331 ++ vasm-1/vasmm68k_std | Bin 0 -> 398628 bytes vasm-1/vobjdump | Bin 0 -> 17508 bytes vasm-1/vobjdump.c | 420 ++ vasm-1/vobjdump.h | 47 + xo-rom-enable-netboot.py | 69 + xo.rom | Bin 0 -> 524288 bytes 200 files changed, 62211 insertions(+) create mode 100644 .gitignore create mode 100755 NetBoot.py create mode 100644 README.md create mode 100644 bbraun-pram/NBPRAM.c create mode 100644 bbraun-pram/pram.c create mode 100644 bbraun-pram/pramtest create mode 100644 bbraun-pram/pramtest.SYM create mode 100644 bbraun-pram/pramtest.proj create mode 100644 vasm-1/Makefile create mode 100644 vasm-1/Makefile.68k create mode 100644 vasm-1/Makefile.Cygwin create mode 100644 vasm-1/Makefile.Haiku create mode 100644 vasm-1/Makefile.MOS create mode 100644 vasm-1/Makefile.MiNT create mode 100644 vasm-1/Makefile.OS4 create mode 100644 vasm-1/Makefile.PUp create mode 100644 vasm-1/Makefile.TOS create mode 100644 vasm-1/Makefile.WOS create mode 100644 vasm-1/Makefile.Win32 create mode 100644 vasm-1/Makefile.Win32FromLinux create mode 100644 vasm-1/atom.c create mode 100644 vasm-1/atom.h create mode 100644 vasm-1/cond.c create mode 100644 vasm-1/cond.h create mode 100644 vasm-1/cpus/6502/cpu.c create mode 100644 vasm-1/cpus/6502/cpu.h create mode 100644 vasm-1/cpus/6502/cpu_errors.h create mode 100644 vasm-1/cpus/6502/opcodes.h create mode 100644 vasm-1/cpus/6800/cpu.c create mode 100644 vasm-1/cpus/6800/cpu.h create mode 100644 vasm-1/cpus/6800/cpu_errors.h create mode 100644 vasm-1/cpus/6800/opcodes.h create mode 100644 vasm-1/cpus/arm/cpu.c create mode 100644 vasm-1/cpus/arm/cpu.h create mode 100644 vasm-1/cpus/arm/cpu_errors.h create mode 100644 vasm-1/cpus/arm/opcodes.h create mode 100644 vasm-1/cpus/c16x/cpu.c create mode 100644 vasm-1/cpus/c16x/cpu.h create mode 100644 vasm-1/cpus/c16x/cpu_errors.h create mode 100644 vasm-1/cpus/c16x/opcodes.h create mode 100644 vasm-1/cpus/jagrisc/cpu.c create mode 100644 vasm-1/cpus/jagrisc/cpu.h create mode 100644 vasm-1/cpus/jagrisc/cpu_errors.h create mode 100644 vasm-1/cpus/jagrisc/opcodes.h create mode 100644 vasm-1/cpus/m68k/cpu.c create mode 100644 vasm-1/cpus/m68k/cpu.h create mode 100644 vasm-1/cpus/m68k/cpu_errors.h create mode 100644 vasm-1/cpus/m68k/cpu_models.h create mode 100644 vasm-1/cpus/m68k/opcodes.h create mode 100644 vasm-1/cpus/m68k/operands.h create mode 100644 vasm-1/cpus/m68k/specregs.h create mode 100644 vasm-1/cpus/ppc/cpu.c create mode 100644 vasm-1/cpus/ppc/cpu.h create mode 100644 vasm-1/cpus/ppc/cpu_errors.h create mode 100644 vasm-1/cpus/ppc/opcodes.h create mode 100644 vasm-1/cpus/ppc/operands.h create mode 100644 vasm-1/cpus/qnice/cpu.c create mode 100644 vasm-1/cpus/qnice/cpu.h create mode 100644 vasm-1/cpus/qnice/cpu_errors.h create mode 100644 vasm-1/cpus/qnice/opcodes.h create mode 100644 vasm-1/cpus/test/cpu.c create mode 100644 vasm-1/cpus/test/cpu.h create mode 100644 vasm-1/cpus/test/cpu_errors.h create mode 100644 vasm-1/cpus/tr3200/cpu.c create mode 100644 vasm-1/cpus/tr3200/cpu.h create mode 100644 vasm-1/cpus/tr3200/cpu_errors.h create mode 100644 vasm-1/cpus/tr3200/opcodes.h create mode 100644 vasm-1/cpus/vidcore/cpu.c create mode 100644 vasm-1/cpus/vidcore/cpu.h create mode 100644 vasm-1/cpus/vidcore/cpu_errors.h create mode 100644 vasm-1/cpus/vidcore/opcodes.h create mode 100644 vasm-1/cpus/x86/cpu.c create mode 100644 vasm-1/cpus/x86/cpu.h create mode 100644 vasm-1/cpus/x86/cpu_errors.h create mode 100644 vasm-1/cpus/x86/opcodes.h create mode 100644 vasm-1/cpus/x86/registers.h create mode 100644 vasm-1/cpus/z80/cpu.c create mode 100644 vasm-1/cpus/z80/cpu.h create mode 100644 vasm-1/cpus/z80/cpu_errors.h create mode 100644 vasm-1/doc/cpu_6502.texi create mode 100644 vasm-1/doc/cpu_6800.texi create mode 100644 vasm-1/doc/cpu_arm.texi create mode 100644 vasm-1/doc/cpu_c16x.texi create mode 100644 vasm-1/doc/cpu_jagrisc.texi create mode 100644 vasm-1/doc/cpu_m68k.texi create mode 100644 vasm-1/doc/cpu_ppc.texi create mode 100644 vasm-1/doc/cpu_tr3200.texi create mode 100644 vasm-1/doc/cpu_x86.texi create mode 100644 vasm-1/doc/cpu_z80.texi create mode 100644 vasm-1/doc/interface.texi create mode 100644 vasm-1/doc/output_aout.texi create mode 100644 vasm-1/doc/output_bin.texi create mode 100644 vasm-1/doc/output_elf.texi create mode 100644 vasm-1/doc/output_hunk.texi create mode 100644 vasm-1/doc/output_srec.texi create mode 100644 vasm-1/doc/output_test.texi create mode 100644 vasm-1/doc/output_tos.texi create mode 100644 vasm-1/doc/output_vobj.texi create mode 100644 vasm-1/doc/output_xfile.texi create mode 100644 vasm-1/doc/syntax_madmac.texi create mode 100644 vasm-1/doc/syntax_mot.texi create mode 100644 vasm-1/doc/syntax_oldstyle.texi create mode 100644 vasm-1/doc/syntax_std.texi create mode 100644 vasm-1/doc/vasm.texi create mode 100644 vasm-1/doc/vasm_main.texi create mode 100644 vasm-1/dwarf.c create mode 100644 vasm-1/dwarf.h create mode 100644 vasm-1/elf_reloc_386.h create mode 100644 vasm-1/elf_reloc_68k.h create mode 100644 vasm-1/elf_reloc_arm.h create mode 100644 vasm-1/elf_reloc_jag.h create mode 100644 vasm-1/elf_reloc_ppc.h create mode 100644 vasm-1/elf_reloc_x86_64.h create mode 100644 vasm-1/error.c create mode 100644 vasm-1/error.h create mode 100644 vasm-1/expr.c create mode 100644 vasm-1/expr.h create mode 100644 vasm-1/general_errors.h create mode 100644 vasm-1/history create mode 100644 vasm-1/hugeint.c create mode 100644 vasm-1/hugeint.h create mode 100644 vasm-1/make.rules create mode 100644 vasm-1/obj/.dummy create mode 100644 vasm-1/obj/m68k_std_atom.o create mode 100644 vasm-1/obj/m68k_std_cond.o create mode 100644 vasm-1/obj/m68k_std_cpu.o create mode 100644 vasm-1/obj/m68k_std_dwarf.o create mode 100644 vasm-1/obj/m68k_std_error.o create mode 100644 vasm-1/obj/m68k_std_expr.o create mode 100644 vasm-1/obj/m68k_std_hugeint.o create mode 100644 vasm-1/obj/m68k_std_osdep.o create mode 100644 vasm-1/obj/m68k_std_output_aout.o create mode 100644 vasm-1/obj/m68k_std_output_bin.o create mode 100644 vasm-1/obj/m68k_std_output_elf.o create mode 100644 vasm-1/obj/m68k_std_output_hunk.o create mode 100644 vasm-1/obj/m68k_std_output_srec.o create mode 100644 vasm-1/obj/m68k_std_output_test.o create mode 100644 vasm-1/obj/m68k_std_output_tos.o create mode 100644 vasm-1/obj/m68k_std_output_vobj.o create mode 100644 vasm-1/obj/m68k_std_output_xfile.o create mode 100644 vasm-1/obj/m68k_std_parse.o create mode 100644 vasm-1/obj/m68k_std_reloc.o create mode 100644 vasm-1/obj/m68k_std_supp.o create mode 100644 vasm-1/obj/m68k_std_symbol.o create mode 100644 vasm-1/obj/m68k_std_symtab.o create mode 100644 vasm-1/obj/m68k_std_syntax.o create mode 100644 vasm-1/obj/m68k_std_vasm.o create mode 100644 vasm-1/obj/vobjdump.o create mode 100644 vasm-1/osdep.c create mode 100644 vasm-1/osdep.h create mode 100644 vasm-1/output_aout.c create mode 100644 vasm-1/output_aout.h create mode 100644 vasm-1/output_bin.c create mode 100644 vasm-1/output_elf.c create mode 100644 vasm-1/output_elf.h create mode 100644 vasm-1/output_errors.h create mode 100644 vasm-1/output_hunk.c create mode 100644 vasm-1/output_hunk.h create mode 100644 vasm-1/output_srec.c create mode 100644 vasm-1/output_test.c create mode 100644 vasm-1/output_tos.c create mode 100644 vasm-1/output_tos.h create mode 100644 vasm-1/output_vobj.c create mode 100644 vasm-1/output_xfile.c create mode 100644 vasm-1/output_xfile.h create mode 100644 vasm-1/parse.c create mode 100644 vasm-1/parse.h create mode 100644 vasm-1/reloc.c create mode 100644 vasm-1/reloc.h create mode 100644 vasm-1/stabs.h create mode 100644 vasm-1/supp.c create mode 100644 vasm-1/supp.h create mode 100644 vasm-1/symbol.c create mode 100644 vasm-1/symbol.h create mode 100644 vasm-1/symtab.c create mode 100644 vasm-1/symtab.h create mode 100644 vasm-1/syntax/madmac/syntax.c create mode 100644 vasm-1/syntax/madmac/syntax.h create mode 100644 vasm-1/syntax/madmac/syntax_errors.h create mode 100644 vasm-1/syntax/mot/syntax.c create mode 100644 vasm-1/syntax/mot/syntax.h create mode 100644 vasm-1/syntax/mot/syntax_errors.h create mode 100644 vasm-1/syntax/oldstyle/syntax.c create mode 100644 vasm-1/syntax/oldstyle/syntax.h create mode 100644 vasm-1/syntax/oldstyle/syntax_errors.h create mode 100644 vasm-1/syntax/std/syntax.c create mode 100644 vasm-1/syntax/std/syntax.h create mode 100644 vasm-1/syntax/std/syntax_errors.h create mode 100644 vasm-1/syntax/test/syntax.c create mode 100644 vasm-1/syntax/test/syntax.h create mode 100644 vasm-1/syntax/test/syntax_errors.h create mode 100644 vasm-1/tfloat.h create mode 100644 vasm-1/vasm.c create mode 100644 vasm-1/vasm.h create mode 100755 vasm-1/vasmm68k_std create mode 100755 vasm-1/vobjdump create mode 100644 vasm-1/vobjdump.c create mode 100644 vasm-1/vobjdump.h create mode 100755 xo-rom-enable-netboot.py create mode 100755 xo.rom diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8144c7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.app +edit.rom +.DS_Store diff --git a/NetBoot.py b/NetBoot.py new file mode 100755 index 0000000..afe2eaf --- /dev/null +++ b/NetBoot.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 + +# Multicast client +# Adapted from: http://chaos.weblogs.us/archives/164 + +import socket + +ANY = "0.0.0.0" +MCAST_ADDR = "239.192.76.84" +MCAST_PORT = 1954 + +# Create a UDP socket +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # IPPROTO_UDP could just be 0 + +# Allow multiple sockets to use the same PORT number +sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) +sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEPORT,1) + +# Bind to the port that we know will receive multicast data +sock.bind((ANY,MCAST_PORT)) + +# Tell the kernel that we want to add ourselves to a multicast group +# The address for the multicast group is the third param +status = sock.setsockopt(socket.IPPROTO_IP, +socket.IP_ADD_MEMBERSHIP, +socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY)) + +# setblocking(0) is equiv to settimeout(0.0) which means we poll the socket. +# But this will raise an error if recv() or send() can't immediately find or send data. +# sock.setblocking(0) + +while 1: + try: + data, addr = sock.recvfrom(1024) + except socket.error as e: + pass + else: + print("From: ", addr) + print("Data: ", data) diff --git a/README.md b/README.md new file mode 100644 index 0000000..e14e371 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +netBOOT for Old World Macs +========================== +Read this thread: https://mac68k.info/forums/thread.jspa?threadID=76&tstart=0 + +Now I'm trying to get it working! The dream is to boot all my Classics over PhoneNet. + + +Progress so far +--------------- +The best build options for Mini vMac are: `-br 37 -m Classic -lt -speed z -as 0 -chr 0`. Note that this requires the new (as of mid-2020) version of Mini vMac, with Rob Mitchelmore's clever LocalTalk-over-UDP tunneling. + +The xo-rom-enable-netboot.py script can edit xo.rom (Macintosh Classic) to force-enable the netBOOT driver (essentially by editing PRAM). (It requires you to build vasm with a quick `make CPU=m68k SYNTAX=std`.) This enables quick iteration: + + cp xo.rom edit.rom && ./xo-rom-enable-netboot.py edit.rom&& Mini\ vMac\ Classic.app/Co*/Ma*/* edit.rom + +Running NetBoot.py simultaneously now shows the netBOOT driver sending DDP packets, and getting no response. + + +Trivia +------ +The Classic is the only non-IIci non-SuperMario ROM with .netBOOT and .ATBOOT drivers. They are part of the overpatch imposed on the SE ROM, and were essentially backported (see the SuperMario forXO.a file). I use the Classic ROM here because it can be emulated in Mini vMac, but the newer netBOOT-equipped ROMs should work. + + +Credits +------- +To all the intrepid individuals on the mac68k forum thread. Join Freenode #mac68k to meet them. + +Credit to bbraun http://synack.net/~bbraun/ for the contents of the "bbraun-pram" dir. diff --git a/bbraun-pram/NBPRAM.c b/bbraun-pram/NBPRAM.c new file mode 100644 index 0000000..39bf7e2 --- /dev/null +++ b/bbraun-pram/NBPRAM.c @@ -0,0 +1 @@ +/* * Initialize netboot pram * - Rob Braun * 2012 */ #include #include #include #include #include void get_netboot_pram(struct netboot *nb); void set_netboot_pram(struct netboot *nb); #pragma parameter __D0 ReadXPRam(__D0, __D1, __A0) short ReadXPRam(short size, short offset, char *where) = {0x4840, 0x3001, _ReadXPRam}; #pragma parameter __D0 WriteXPRam(__D0, __D1, __A0) short WriteXPRam(short size, short offset, char *where) = {0x4840, 0x3001, _WriteXPRam}; struct netboot { char machineID; /* this is used as part of the boot protocol */ char protocol; char errors; char flags; /* Used to enable netbooting, and allow guest netbooting */ char intervalCount; /* high nibble is the retry count, low nibble is the interval between retries */ char timeout; unsigned long signature[4]; char userName[31]; char password[8]; short serverID; /* the value here will be translated to ascii encoded hex and used as the server name to boot from. */ char padding[7]; }; void get_netboot_pram(struct netboot *nb) { char *i = (char*)nb; ReadXPRam(4, 4, i); i += 4; ReadXPRam(3, 0xAB, i); i += 3; ReadXPRam(1, 0xBC, i); i++; ReadXPRam(0x20, 0x20, i); i += 0x20; ReadXPRam(0x20, 0x8B, i); return; } void set_netboot_pram(struct netboot *nb) { char *i = (char*)nb; WriteXPRam(4, 4, i); i += 4; WriteXPRam(3, 0xAB, i); i += 3; WriteXPRam(1, 0xBC, i); i++; WriteXPRam(0x20, 0x20, i); i += 0x20; WriteXPRam(0x20, 0x8B, i); return; } void main(void) { struct netboot nb; char *i; int n; memset(&nb, 0, sizeof(nb)); get_netboot_pram(&nb); for(i = (char*)&nb, n = 0; n < sizeof(nb); n++) { printf("0x%x ", i[n]); } printf("\n"); #if 1 memset(&nb, 0, sizeof(nb)); nb.machineID = 1; nb.protocol = 1; nb.errors = 0; nb.flags = 0xC0; nb.intervalCount = 0x24; /* low nibble is interval, high nibble is count for lookups */ nb.timeout = 127; nb.signature[0] = 'PWD '; //nb.userName[0] = '\0'; strcpy(nb.userName, "bbraun"); nb.password[0] = '\0'; nb.serverID = 0xEBAB; set_netboot_pram(&nb); #endif } \ No newline at end of file diff --git a/bbraun-pram/pram.c b/bbraun-pram/pram.c new file mode 100644 index 0000000..3d3812a --- /dev/null +++ b/bbraun-pram/pram.c @@ -0,0 +1,7 @@ +scal void read_extended_PRAM(char * where, const short size) = +{ 0x4280, 0x301F, 0x4840, 0x205F, 0xA051 }; + +pascal void write_extended_PRAM + (const char * where, const short offset, const short size) = +{0x201F, 0x205F, 0xA052}; + diff --git a/bbraun-pram/pramtest b/bbraun-pram/pramtest new file mode 100644 index 0000000..e69de29 diff --git a/bbraun-pram/pramtest.SYM b/bbraun-pram/pramtest.SYM new file mode 100644 index 0000000000000000000000000000000000000000..4606eec7f7c3bae82dbe66ca24bfffd3b9508922 GIT binary patch literal 110592 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 literal 0 HcmV?d00001 diff --git a/bbraun-pram/pramtest.proj b/bbraun-pram/pramtest.proj new file mode 100644 index 0000000000000000000000000000000000000000..dfffcca71d0156cb91e0ec2c6eb26dc342931881 GIT binary patch literal 4279 zcmcIneQZ=!7C-mRdo$DTf!g{7>sx}PhzzwG5skpmGB{;B(_#7nZj3N(hjvIiGyCQh zaF@hxHU7aGV-|KdMw8_avS9_9O?Gvwi-e%rP1ucbjWK~>P-9diD26PHEB5X0+;?AF zI>pAAz0G~UbI!fz-rxN=XKs7*`9UHQs0)Z{4x|1Z@+H(t^5Hu`8a1LeRIf{Pw3=<% z9xH8SGsXJ{oc}~9fF4|esAA1EqI=h9g#JVgRq=H1RCjtv_V;sV6!sJP$CzZ3)W2(g z@FCy(zoLpRi?kP3iQ;o7Fpe&Mdj1_X-Xv%sq^;E=k2~})@uj$|t=85;ew!uWIdMvy z0e-6V^V9lVh;MFhj;~zxV>K8?8vT%H{sYioEN$ES6ww`P(e{_pwiVb>-^*w-O51kx z?s3sd+lEhJa|>t-mbTq|6UO`iZ2=MygQzT3)sh?>E^-YIW_x(Z>&w{Y3(t#@c(QE+ zOQf+^#cgFcsrHW9J=lM&tKoI!1&Mret~;wbTHCv}gt0qeT#D=GkzO6AJugV4ORsn9 z*2TlUrAv~Qe{Q&9i;>RgmQI!^7(tW-FI8d>W0`bc z#wvyfX7N0F(A?#Eu|#FA7srV5n!07vyvMqhP0&a@-V&2ic?1kYw+D)LUp7DMG}8BI zC9ap0DqXK2=E7CF;bb%Bs&c*jc6KOpLm#3UUe%Lx zS=n6w4gF?#)kJih*MUH%l`eeCx{mzt%ZR%!DUsHMlSZUc8HqvMTX7IF=Rcb3Zb@PhLVy*~L`3KpK zV+Cx~D2qQL;tb@DGFQZ?Ooe>Ju`@MF=Z}auSGl9i72_(W0meASJuX^p1Ch*Xa$o1l zFYt4V#+e49yCUte&xknxsTIu;%_>h4`8lqqMycIG#FkON@#B9k=Ts(f19q{vnNHMNJxCJt9 zn{U1}yAi~q8y&9E-ERE8MEj#VVB(v=zhfpYu9@h@Eh}G~!%v%T>E^~*q){B$v}JF> z*YqGA_Vn((1p)n-r>FK7Ow07N=x1aWOtk;fvn<}4cr-EmY=6eyn#ieXl_U#jJi_R1C*KAN)49Bbho63)2%zS10aUR}7yIpO>j z`eNr8zK=VvE#H&eyxw$e1WWQBX=YGhq`2Jv0 zua|z?SV!T#r077$!|@o7zz-$JmXad#7;f%Hw4j$B2bKdlpz47?10pK)CxAf`{>EAb1#W0l~vK3j_~8xjZm5&psy)Kkpwn z`uWw1dHs(77XfV`5|RH9FakV5MA$n&XLoS*p9b~;uK>Y0PzEdjZwJCRundSj4Xg%^ z0Dl8~3it=$Gr+HbF90Wi2SA}7_$$`v2>WB$yGSIW1AS>20Th01MfP^%TU2)XCTTqh)BWE{RP)7F4oBhQ#` zl)I{{Qu6vdQ<6rt6}cYromHuoMBPxjcOaX~w5}(5sbJ;pd@uf&)c&2Zth`kuA+`^u z`++~n=Io4x$7f4^IA@cul^=)sVVgv*nC;J{?O_XH^wn@NVApTZ4@qRRcrTUa*jpki??YUyh^$=Ii2p$W_YnO_<``{b0WV8?J836} zGDC31+&Maa_|*$?7u=}gQ~4f6CK}zu$?=ikuu3*in$<`4HgFaF?&P7;^-Sw7d;4)c zf(dEWRp#`%IKImpks8I{aG&l&BMho&iJNo#E>K5^UXX6K_vUPhlem*Lj<=OZ#sB8#bcRYUDDcg&ljUQ@m Y333WK!}Ib3-7VF8;s4QN?JBbEe;UFC-2eap literal 0 HcmV?d00001 diff --git a/vasm-1/Makefile b/vasm-1/Makefile new file mode 100644 index 0000000..46ad3e3 --- /dev/null +++ b/vasm-1/Makefile @@ -0,0 +1,18 @@ +# Unix +# Define CC, when no compiler with the name "cc" exists. + +TARGET = +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CCOUT = -o +COPTS = -c -O2 -DUNIX $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm + +RM = rm -f + +include make.rules diff --git a/vasm-1/Makefile.68k b/vasm-1/Makefile.68k new file mode 100644 index 0000000..b4658f2 --- /dev/null +++ b/vasm-1/Makefile.68k @@ -0,0 +1,18 @@ +# AmigaOS/68k + +TARGET = _os3 +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = vc +aos68k +CCOUT = -o +COPTS = -c -c99 -cpu=68020 -DAMIGA $(OUTFMTS) -O1 + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lmieee + +RM = delete force quiet + +include make.rules diff --git a/vasm-1/Makefile.Cygwin b/vasm-1/Makefile.Cygwin new file mode 100644 index 0000000..dfc584b --- /dev/null +++ b/vasm-1/Makefile.Cygwin @@ -0,0 +1,18 @@ +# Windows compiled with gcc + +TARGET = _win32 +TARGETEXTENSION = .exe +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = gcc +CCOUT = -o +COPTS = -c -O2 -DUNIX $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm + +RM = rm -f + +include make.rules diff --git a/vasm-1/Makefile.Haiku b/vasm-1/Makefile.Haiku new file mode 100644 index 0000000..05e0096 --- /dev/null +++ b/vasm-1/Makefile.Haiku @@ -0,0 +1,18 @@ +# Unix + +TARGET = +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = gcc +CCOUT = -o +COPTS = -c -O2 $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = + +RM = rm -f + +include make.rules diff --git a/vasm-1/Makefile.MOS b/vasm-1/Makefile.MOS new file mode 100644 index 0000000..9abda33 --- /dev/null +++ b/vasm-1/Makefile.MOS @@ -0,0 +1,18 @@ +# MorphOS + +TARGET = _mos +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = vc +morphos +CCOUT = -o +COPTS = -c -DAMIGA -O1 $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm + +RM = delete force quiet + +include make.rules diff --git a/vasm-1/Makefile.MiNT b/vasm-1/Makefile.MiNT new file mode 100644 index 0000000..996da19 --- /dev/null +++ b/vasm-1/Makefile.MiNT @@ -0,0 +1,18 @@ +# Atari TOS/MiNT + +TARGET = _MiNT +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = vc +mint +CCOUT = -o +COPTS = -c -c99 -cpu=68020 -O1 $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm + +RM = rm -f + +include make.rules diff --git a/vasm-1/Makefile.OS4 b/vasm-1/Makefile.OS4 new file mode 100644 index 0000000..b4bec72 --- /dev/null +++ b/vasm-1/Makefile.OS4 @@ -0,0 +1,18 @@ +# AmigaOS 4.x/PPC + +TARGET = _os4 +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = vc +aosppc +CCOUT = -o +COPTS = -c -DAMIGA -D__USE_INLINE__ -O1 $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm + +RM = delete force quiet + +include make.rules diff --git a/vasm-1/Makefile.PUp b/vasm-1/Makefile.PUp new file mode 100644 index 0000000..91c0fe7 --- /dev/null +++ b/vasm-1/Makefile.PUp @@ -0,0 +1,18 @@ +# PowerUp + +TARGET = _pup +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = vc +powerup +CCOUT = -o +COPTS = -c -c99 -DAMIGA -O1 $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm -lamiga + +RM = delete force quiet + +include make.rules diff --git a/vasm-1/Makefile.TOS b/vasm-1/Makefile.TOS new file mode 100644 index 0000000..1608a17 --- /dev/null +++ b/vasm-1/Makefile.TOS @@ -0,0 +1,18 @@ +# Atari TOS + +TARGET = _TOS +TARGETEXTENSION = .ttp +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = vc +tos +CCOUT = -o +COPTS = -c -c99 -O1 -DATARI $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm + +RM = rm -f + +include make.rules diff --git a/vasm-1/Makefile.WOS b/vasm-1/Makefile.WOS new file mode 100644 index 0000000..ff0b062 --- /dev/null +++ b/vasm-1/Makefile.WOS @@ -0,0 +1,18 @@ +# WarpOS + +TARGET = _wos +TARGETEXTENSION = +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +CC = vc +warpos +CCOUT = -o +COPTS = -c -c99 -DAMIGA -O1 $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm -lamiga + +RM = delete force quiet + +include make.rules diff --git a/vasm-1/Makefile.Win32 b/vasm-1/Makefile.Win32 new file mode 100644 index 0000000..5688ab4 --- /dev/null +++ b/vasm-1/Makefile.Win32 @@ -0,0 +1,30 @@ +# Windows +# Tested with Visual Studio 2017: works fine under the Developer Command Prompt for VS2017 +# Tested with Visual Studio 2005 Express Edition: works fine +# Tested with Visual C++ Toolkit 2003: works fine, but needs an external make tool (nmake is not included) + +TARGET = _win32 +TARGETEXTENSION = .exe +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + +# If Visual Studio is unable to find when compiling vlink, try enabling the two +# lines below, and point them to where you have installed the Win32 Platform SDK. + +#WIN32_PLATFORMSDK_INCLUDE = "/IC:\Code\Win32 Platform SDK\Include" +#WIN32_PLATFORMSDK_LIB = "/LIBPATH:C:\Code\Win32 Platform SDK\Lib" + +CC = cl +CCOUT = /Fo +COPTS = $(OUTFMTS) /nologo /O2 /MT /c +COPTS = $(COPTS) /wd4996 # Disable warning regarding deprecated functions + # ("use strcpy_s instead of strcpy" etc) +COPTS = $(COPTS) $(WIN32_PLATFORMSDK_INCLUDE) + +LD = link +LDOUT = /OUT: +LDFLAGS = /NOLOGO $(WIN32_PLATFORMSDK_LIB) + +RM = rem + +include make.rules diff --git a/vasm-1/Makefile.Win32FromLinux b/vasm-1/Makefile.Win32FromLinux new file mode 100644 index 0000000..2134417 --- /dev/null +++ b/vasm-1/Makefile.Win32FromLinux @@ -0,0 +1,22 @@ +# Windows compiled on a Linux machine with mingw + +TARGET = _win32 +TARGETEXTENSION = .exe +OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \ + -DOUTXFIL + + +#CC = /usr/bin/i586-mingw32msvc-gcc +CC = /usr/bin/i686-w64-mingw32-gcc +CCOUT = -o +COPTS = -c -O2 $(OUTFMTS) + +LD = $(CC) +LDOUT = $(CCOUT) +LDFLAGS = -lm + +RM = rm -f + + + +include make.rules diff --git a/vasm-1/atom.c b/vasm-1/atom.c new file mode 100644 index 0000000..becdba4 --- /dev/null +++ b/vasm-1/atom.c @@ -0,0 +1,672 @@ +/* atom.c - atomic objects from source */ +/* (c) in 2010-2020 by Volker Barthelmann and Frank Wille */ + +#include "vasm.h" + + +/* searches mnemonic list and tries to parse (via the cpu module) + the operands according to the mnemonic requirements; returns an + instruction or 0 */ +instruction *new_inst(char *inst,int len,int op_cnt,char **op,int *op_len) +{ +#if MAX_OPERANDS!=0 + operand ops[MAX_OPERANDS]; + int j,k,mnemo_opcnt,omitted,skipped; +#endif + int i,inst_found=0; + hashdata data; + instruction *new; + + new = mymalloc(sizeof(*new)); +#if HAVE_INSTRUCTION_EXTENSION + init_instruction_ext(&new->ext); +#endif +#if MAX_OPERANDS!=0 && NEED_CLEARED_OPERANDS!=0 + /* reset operands to allow the cpu-backend to parse them only once */ + memset(ops,0,sizeof(ops)); +#endif + + if (find_namelen_nc(mnemohash,inst,len,&data)) { + i = data.idx; + + /* try all mnemonics with the same name until operands match */ + do { + inst_found = 1; + if (!MNEMONIC_VALID(i)) { + i++; + continue; /* try next */ + } + +#if MAX_OPERANDS!=0 + +#if ALLOW_EMPTY_OPS + mnemo_opcnt = op_cnt= op_cnt) /* missing mandatory operands */ + break; + + rc = parse_operand(op[k],op_len[k],&ops[j], + mnemonics[i].operand_type[j]); + + if (rc == PO_CORRUPT) { + myfree(new); + restore_symbols(); + return 0; + } + if (rc == PO_NOMATCH) + break; + + /* MATCH, move to next parsed operand */ + k++; + if (rc == PO_SKIP) { /* but skip next operand type from table */ + j++; + skipped++; + } + } + } + +#if IGNORE_FIRST_EXTRA_OP + if (mnemo_opcnt > 0) +#endif + if (jop[j] = mymalloc(sizeof(operand)); + *new->op[j] = ops[j]; + } + for(; jop[j] = 0; + +#endif /* MAX_OPERANDS!=0 */ + + new->code = i; + return new; + } + while (isize = 0; + new->data = 0; + new->relocs = 0; + return new; +} + + +sblock *new_sblock(expr *space,size_t size,expr *fill) +{ + sblock *sb = mymalloc(sizeof(sblock)); + + sb->space = 0; + sb->space_exp = space; + sb->size = size; + if (!(sb->fill_exp = fill)) + memset(sb->fill,0,MAXPADBYTES); + sb->relocs = 0; + sb->maxalignbytes = 0; + sb->flags = 0; + return sb; +} + + +static size_t space_size(sblock *sb,section *sec,taddr pc) +{ + utaddr space=0; + + if (eval_expr(sb->space_exp,&space,sec,pc) || !final_pass) + sb->space = space; + else + general_error(30); /* expression must be constant */ + + if (final_pass && sb->fill_exp) { + if (sb->size <= sizeof(taddr)) { + /* space is filled with an expression which may also need relocations */ + symbol *base=NULL; + taddr fill; + utaddr i; + + if (!eval_expr(sb->fill_exp,&fill,sec,pc)) { + if (find_base(sb->fill_exp,&base,sec,pc)==BASE_ILLEGAL) + general_error(38); /* illegal relocation */ + } + copy_cpu_taddr(sb->fill,fill,sb->size); + if (base && !sb->relocs) { + /* generate relocations */ + for (i=0; irelocs,base,fill,REL_ABS, + 0,sb->size<<3,sb->size*i); + } + } + else + general_error(30); /* expression must be constant */ + } + + return sb->size * space; +} + + +static size_t roffs_size(reloffs *roffs,section *sec,taddr pc) +{ + taddr offs; + + eval_expr(roffs->offset,&offs,sec,pc); + offs = sec->org + offs - pc; + return offs>0 ? offs : 0; +} + + +/* adds an atom to the specified section; if sec==0, the current + section is used */ +void add_atom(section *sec,atom *a) +{ + if (!sec) { + sec = default_section(); + if (!sec) { + general_error(3); + return; + } + } + + a->changes = 0; + a->src = cur_src; + a->line = cur_src!=NULL ? cur_src->line : 0; + + if (sec->last) { + atom *pa = sec->last; + + pa->next = a; + /* make sure that a label on the same line gets the same alignment */ + if (pa->type==LABEL && pa->line==a->line && + (a->type==INSTRUCTION || a->type==DATADEF || a->type==SPACE)) + pa->align = a->align; + } + else + sec->first = a; + a->next = 0; + sec->last = a; + + sec->pc = pcalign(a,sec->pc); + a->lastsize = atom_size(a,sec,sec->pc); + sec->pc += a->lastsize; + if (a->align > sec->align) + sec->align = a->align; + + if (listena) { + a->list = last_listing; + if (last_listing) { + if (!last_listing->atom) + last_listing->atom = a; + } + } + else + a->list = 0; +} + + +size_t atom_size(atom *p,section *sec,taddr pc) +{ + switch(p->type) { + case VASMDEBUG: + case LABEL: + case LINE: + case OPTS: + case PRINTTEXT: + case PRINTEXPR: + case RORG: + case RORGEND: + case ASSERT: + case NLIST: /* it has a size, but not in the current section */ + return 0; + case DATA: + return p->content.db->size; + case INSTRUCTION: + return p->content.inst->code>=0? + instruction_size(p->content.inst,sec,pc):0; + case SPACE: + return space_size(p->content.sb,sec,pc); + case DATADEF: + return (p->content.defb->bitsize+7)/8; + case ROFFS: + return roffs_size(p->content.roffs,sec,pc); + default: + ierror(0); + break; + } + return 0; +} + + +static void print_instruction(FILE *f,instruction *p) +{ + int i; + + printf("inst %d(%s) ",p->code,p->code>=0?mnemonics[p->code].name:"deleted"); +#if MAX_OPERANDS!=0 + for (i=0; iop[i]); +#endif +} + + +void print_atom(FILE *f,atom *p) +{ + size_t i; + rlist *rl; + + switch (p->type) { + case VASMDEBUG: + fprintf(f,"vasm debug directive"); + break; + case LABEL: + fprintf(f,"symbol: "); + print_symbol(f,p->content.label); + break; + case DATA: + fprintf(f,"data(%lu): ",(unsigned long)p->content.db->size); + for (i=0;icontent.db->size;i++) + fprintf(f,"%02x ",p->content.db->data[i]); + for (rl=p->content.db->relocs; rl; rl=rl->next) + print_reloc(f,rl->type,rl->reloc); + break; + case INSTRUCTION: + print_instruction(f,p->content.inst); + break; + case SPACE: + fprintf(f,"space(%lu,fill=", + (unsigned long)(p->content.sb->space*p->content.sb->size)); + for (i=0; icontent.sb->size; i++) + fprintf(f,"%02x%c",(unsigned char)p->content.sb->fill[i], + (i==p->content.sb->size-1)?')':' '); + for (rl=p->content.sb->relocs; rl; rl=rl->next) + print_reloc(f,rl->type,rl->reloc); + break; + case DATADEF: + fprintf(f,"datadef(%lu bits)",(unsigned long)p->content.defb->bitsize); + break; + case LINE: + fprintf(f,"line: %d of %s",p->content.srcline,getdebugname()); + break; +#if HAVE_CPU_OPTS + case OPTS: + print_cpu_opts(f,p->content.opts); + break; +#endif + case PRINTTEXT: + fprintf(f,"text: \"%s\"",p->content.ptext); + break; + case PRINTEXPR: + fprintf(f,"expr: "); + print_expr(f,p->content.pexpr->print_exp); + break; + case ROFFS: + fprintf(f,"roffs: offset "); + print_expr(f,p->content.roffs->offset); + fprintf(f,",fill="); + if (p->content.roffs->fillval) + print_expr(f,p->content.roffs->fillval); + else + fprintf(f,"none"); + break; + case RORG: + fprintf(f,"rorg: relocate to 0x%llx",ULLTADDR(*p->content.rorg)); + break; + case RORGEND: + fprintf(f,"rorg end"); + break; + case ASSERT: + fprintf(f,"assert: %s (message: %s)\n",p->content.assert->expstr, + p->content.assert->msgstr?p->content.assert->msgstr:emptystr); + break; + case NLIST: + fprintf(f,"nlist: %s (type %d, other %d, desc %d) with value ", + p->content.nlist->name!=NULL ? p->content.nlist->name : "", + p->content.nlist->type,p->content.nlist->other, + p->content.nlist->desc); + if (p->content.nlist->value != NULL) + print_expr(f,p->content.nlist->value); + else + fprintf(f,"NULL"); + break; + default: + ierror(0); + } +} + + +/* prints and formats an expression from a PRINTEXPR atom */ +void atom_printexpr(printexpr *pexp,section *sec,taddr pc) +{ + taddr t; + long long v; + int i; + + eval_expr(pexp->print_exp,&t,sec,pc); + if (pexp->type==PEXP_SDEC && (t&(1LL<<(pexp->size-1)))!=0) { + /* signed decimal */ + v = -1; + v &= ~(long long)MAKEMASK(pexp->size); + } + else + v = 0; + v |= t & MAKEMASK(pexp->size); + + switch (pexp->type) { + case PEXP_HEX: + printf("%llX",(unsigned long long)v); + break; + case PEXP_SDEC: + printf("%lld",v); + break; + case PEXP_UDEC: + printf("%llu",(unsigned long long)v); + break; + case PEXP_BIN: + for (i=pexp->size-1; i>=0; i--) + putchar((v & (1LL<size+7)>>3)-1; i>=0; i--) { + unsigned char c = (v>>(i*8))&0xff; + putchar(isprint(c) ? c : '.'); + } + break; + default: + ierror(0); + break; + } +} + + +atom *clone_atom(atom *a) +{ + atom *new = mymalloc(sizeof(atom)); + void *p; + + memcpy(new,a,sizeof(atom)); + + switch (a->type) { + /* INSTRUCTION and DATADEF have to be cloned as well, because they will + be deallocated and transformed into DATA during assemble() */ + case INSTRUCTION: + p = mymalloc(sizeof(instruction)); + memcpy(p,a->content.inst,sizeof(instruction)); + new->content.inst = p; + break; + case DATADEF: + p = mymalloc(sizeof(defblock)); + memcpy(p,a->content.defb,sizeof(defblock)); + new->content.defb = p; + break; + default: + break; + } + + new->next = 0; + new->src = NULL; + new->line = 0; + new->list = NULL; + return new; +} + + +atom *add_data_atom(section *sec,size_t sz,taddr alignment,taddr c) +{ + dblock *db = new_dblock(); + atom *a; + + db->size = sz; + db->data = mymalloc(sz); + if (sz > 1) + setval(BIGENDIAN,db->data,sz,c); + else + *(db->data) = c; + + a = new_data_atom(db,alignment); + add_atom(sec,a); + return a; +} + + +void add_leb128_atom(section *sec,taddr c) +{ + taddr b; + + do { + b = c & 0x7f; + if ((c >>= 7) != 0) + b |= 0x80; + add_data_atom(sec,1,1,b); + } while (c != 0); +} + + +void add_sleb128_atom(section *sec,taddr c) +{ + int done = 0; + taddr b; + + do { + b = c & 0x7f; + c >>= 7; /* assumes arithmetic shifts! */ + if ((c==0 && !(b&0x40)) || (c==-1 && (b&0x40))) + done = 1; + else + b |= 0x80; + add_data_atom(sec,1,1,b); + } while (!done); +} + + +atom *add_bytes_atom(section *sec,void *p,size_t sz) +{ + dblock *db = new_dblock(); + atom *a; + + db->size = sz; + db->data = mymalloc(sz); + memcpy(db->data,p,sz); + a = new_data_atom(db,1); + add_atom(sec,a); + return a; +} + + +atom *new_atom(int type,taddr align) +{ + atom *new = mymalloc(sizeof(*new)); + + new->next = NULL; + new->type = type; + new->align = align; + return new; +} + + +atom *new_inst_atom(instruction *p) +{ + atom *new = new_atom(INSTRUCTION,inst_alignment); + + new->content.inst = p; + return new; +} + + +atom *new_data_atom(dblock *p,taddr align) +{ + atom *new = new_atom(DATA,align); + + new->content.db = p; + return new; +} + + +atom *new_label_atom(symbol *p) +{ + atom *new = new_atom(LABEL,1); + + new->content.label = p; + return new; +} + + +atom *new_space_atom(expr *space,size_t size,expr *fill) +{ + atom *new = new_atom(SPACE,1); + int i; + + if (size<1) + ierror(0); /* usually an error in syntax-module */ + new->content.sb = new_sblock(space,size,fill); + return new; +} + + +atom *new_datadef_atom(size_t bitsize,operand *op) +{ + atom *new = new_atom(DATADEF,DATA_ALIGN(bitsize)); + + new->content.defb = mymalloc(sizeof(*new->content.defb)); + new->content.defb->bitsize = bitsize; + new->content.defb->op = op; + return new; +} + + +atom *new_srcline_atom(int line) +{ + atom *new = new_atom(LINE,1); + + new->content.srcline = line; + return new; +} + + +atom *new_opts_atom(void *o) +{ + atom *new = new_atom(OPTS,1); + + new->content.opts = o; + return new; +} + + +atom *new_text_atom(char *txt) +{ + atom *new = new_atom(PRINTTEXT,1); + + new->content.ptext = txt ? txt : "\n"; + return new; +} + + +atom *new_expr_atom(expr *exp,int type,int size) +{ + atom *new = new_atom(PRINTEXPR,1); + + new->content.pexpr = mymalloc(sizeof(*new->content.pexpr)); + if (exp==NULL || typePEXP_ASC || size<1 + || size>sizeof(long long)*8) + ierror(0); + new->content.pexpr->print_exp = exp; + new->content.pexpr->type = type; + new->content.pexpr->size = size; + return new; +} + + +atom *new_roffs_atom(expr *offs,expr *fill) +{ + atom *new = new_atom(ROFFS,1); + + new->content.roffs = mymalloc(sizeof(*new->content.roffs)); + new->content.roffs->offset = offs; + new->content.roffs->fillval = fill; + return new; +} + + +atom *new_rorg_atom(taddr raddr) +{ + atom *new = new_atom(RORG,1); + taddr *newrorg = mymalloc(sizeof(taddr)); + + *newrorg = raddr; + new->content.rorg = newrorg; + return new; +} + + +atom *new_rorgend_atom(void) +{ + return new_atom(RORGEND,1); +} + + +atom *new_assert_atom(expr *aexp,char *exp,char *msg) +{ + atom *new = new_atom(ASSERT,1); + + new->content.assert = mymalloc(sizeof(*new->content.assert)); + new->content.assert->assert_exp = aexp; + new->content.assert->expstr = exp; + new->content.assert->msgstr = msg; + return new; +} + + +atom *new_nlist_atom(char *name,int type,int other,int desc,expr *value) +{ + atom *new = new_atom(NLIST,1); + + new->content.nlist = mymalloc(sizeof(*new->content.nlist)); + new->content.nlist->name = name; + new->content.nlist->type = type; + new->content.nlist->other = other; + new->content.nlist->desc = desc; + new->content.nlist->value = value; + return new; +} diff --git a/vasm-1/atom.h b/vasm-1/atom.h new file mode 100644 index 0000000..3337898 --- /dev/null +++ b/vasm-1/atom.h @@ -0,0 +1,152 @@ +/* atom.h - atomic objects from source */ +/* (c) in 2010-2020 by Volker Barthelmann and Frank Wille */ + +#ifndef ATOM_H +#define ATOM_H + +/* types of atoms */ +#define VASMDEBUG 0 +#define LABEL 1 +#define DATA 2 +#define INSTRUCTION 3 +#define SPACE 4 +#define DATADEF 5 +#define LINE 6 +#define OPTS 7 +#define PRINTTEXT 8 +#define PRINTEXPR 9 +#define ROFFS 10 +#define RORG 11 +#define RORGEND 12 +#define ASSERT 13 +#define NLIST 14 + +/* a machine instruction */ +typedef struct instruction { + int code; +#if MAX_QUALIFIERS!=0 + char *qualifiers[MAX_QUALIFIERS]; +#endif +#if MAX_OPERANDS!=0 + operand *op[MAX_OPERANDS]; +#endif +#if HAVE_INSTRUCTION_EXTENSION + instruction_ext ext; +#endif +} instruction; + +typedef struct defblock { + size_t bitsize; + operand *op; +} defblock; + +struct dblock { + size_t size; + unsigned char *data; + rlist *relocs; +}; + +struct sblock { + size_t space; + expr *space_exp; /* copied to space, when evaluated as constant */ + size_t size; + uint8_t fill[MAXPADBYTES]; + expr *fill_exp; /* copied to fill, when evaluated - may be NULL */ + rlist *relocs; + taddr maxalignbytes; + uint32_t flags; +}; +#define SPC_DATABSS 1 /* make sure no to allocate space in a data section */ + +typedef struct reloffs { + expr *offset; + expr *fillval; +} reloffs; + +typedef struct printexpr { + expr *print_exp; + short type; /* hex, signed, unsigned */ + short size; /* precision in bits */ +} printexpr; +#define PEXP_HEX 0 +#define PEXP_SDEC 1 +#define PEXP_UDEC 2 +#define PEXP_BIN 3 +#define PEXP_ASC 4 + +typedef struct assertion { + expr *assert_exp; + char *expstr; + char *msgstr; +} assertion; + +typedef struct aoutnlist { + char *name; + int type; + int other; + int desc; + expr *value; +} aoutnlist; + +/* an atomic element of data */ +typedef struct atom { + struct atom *next; + int type; + taddr align; + size_t lastsize; + unsigned changes; + source *src; + int line; + listing *list; + union { + instruction *inst; + dblock *db; + symbol *label; + sblock *sb; + defblock *defb; + void *opts; + int srcline; + char *ptext; + printexpr *pexpr; + reloffs *roffs; + taddr *rorg; + assertion *assert; + aoutnlist *nlist; + } content; +} atom; + +#define MAXSIZECHANGES 5 /* warning, when atom changed size so many times */ + +instruction *new_inst(char *inst,int len,int op_cnt,char **op,int *op_len); +dblock *new_dblock(); +sblock *new_sblock(expr *,size_t,expr *); + +atom *new_atom(int,taddr); +void add_atom(section *,atom *); +size_t atom_size(atom *,section *,taddr); +void print_atom(FILE *,atom *); +void atom_printexpr(printexpr *,section *,taddr); +atom *clone_atom(atom *); + +atom *add_data_atom(section *,size_t,taddr,taddr); +void add_leb128_atom(section *,taddr); +void add_sleb128_atom(section *,taddr); +atom *add_bytes_atom(section *,void *,size_t); +#define add_string_atom(s,p) add_bytes_atom(s,p,strlen(p)+1) + +atom *new_inst_atom(instruction *); +atom *new_data_atom(dblock *,taddr); +atom *new_label_atom(symbol *); +atom *new_space_atom(expr *,size_t,expr *); +atom *new_datadef_atom(size_t,operand *); +atom *new_srcline_atom(int); +atom *new_opts_atom(void *); +atom *new_text_atom(char *); +atom *new_expr_atom(expr *,int,int); +atom *new_roffs_atom(expr *,expr *); +atom *new_rorg_atom(taddr); +atom *new_rorgend_atom(void); +atom *new_assert_atom(expr *,char *,char *); +atom *new_nlist_atom(char *,int,int,int,expr *); + +#endif diff --git a/vasm-1/cond.c b/vasm-1/cond.c new file mode 100644 index 0000000..dd46320 --- /dev/null +++ b/vasm-1/cond.c @@ -0,0 +1,85 @@ +/* cond.c - conditional assembly support routines */ +/* (c) in 2015 by Frank Wille */ + +#include "vasm.h" + +int clev; /* conditional level */ + +static char cond[MAXCONDLEV+1]; +static char *condsrc[MAXCONDLEV+1]; +static int condline[MAXCONDLEV+1]; +static int ifnesting; + + +/* initialize conditional assembly */ +void cond_init(void) +{ + cond[0] = 1; + clev = ifnesting = 0; +} + + +/* return true, when current level allows assembling */ +int cond_state(void) +{ + return cond[clev]; +} + + +/* ensures that all conditional block are closed at the end of the source */ +void cond_check(void) +{ + if (clev > 0) + general_error(66,condsrc[clev],condline[clev]); /* "endc/endif missing */ +} + + +/* establish a new level of conditional assembly */ +void cond_if(char flag) +{ + if (++clev >= MAXCONDLEV) + general_error(65,clev); /* nesting depth exceeded */ + + cond[clev] = flag; + condsrc[clev] = cur_src->name; + condline[clev] = cur_src->line; +} + + +/* handle skipped if statement */ +void cond_skipif(void) +{ + ifnesting++; +} + + +/* handle else statement after skipped if-branch */ +void cond_else(void) +{ + if (ifnesting == 0) + cond[clev] = 1; +} + + +/* handle else statement after assembled if-branch */ +void cond_skipelse(void) +{ + if (clev > 0) + cond[clev] = 0; + else + general_error(63); /* else without if */ +} + + +/* handle end-if statement */ +void cond_endif(void) +{ + if (ifnesting == 0) { + if (clev > 0) + clev--; + else + general_error(64); /* unexpected endif without if */ + } + else /* the whole conditional block was ignored */ + ifnesting--; +} diff --git a/vasm-1/cond.h b/vasm-1/cond.h new file mode 100644 index 0000000..90a155c --- /dev/null +++ b/vasm-1/cond.h @@ -0,0 +1,25 @@ +/* cond.h - conditional assembly support routines */ +/* (c) in 2015 by Frank Wille */ + +#ifndef COND_H +#define COND_H + +/* defines */ +#ifndef MAXCONDLEV +#define MAXCONDLEV 63 +#endif + +/* global variables */ +extern int clev; + +/* functions */ +void cond_init(void); +int cond_state(void); +void cond_check(void); +void cond_if(char); +void cond_skipif(void); +void cond_else(void); +void cond_skipelse(void); +void cond_endif(void); + +#endif /* COND_H */ diff --git a/vasm-1/cpus/6502/cpu.c b/vasm-1/cpus/6502/cpu.c new file mode 100644 index 0000000..db08c51 --- /dev/null +++ b/vasm-1/cpus/6502/cpu.c @@ -0,0 +1,588 @@ +/* +** cpu.c 650x/65C02/6510/6280 cpu-description file +** (c) in 2002,2006,2008-2012,2014-2020 by Frank Wille +*/ + +#include "vasm.h" + +mnemonic mnemonics[] = { +#include "opcodes.h" +}; + +int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]); + +char *cpu_copyright="vasm 6502 cpu backend 0.8c (c) 2002,2006,2008-2012,2014-2020 Frank Wille"; +char *cpuname = "6502"; +int bitsperbyte = 8; +int bytespertaddr = 2; + +static uint16_t cpu_type = M6502; +static int branchopt = 0; +static int modifier; /* set by find_base() */ +static utaddr dpage = 0; /* default zero/direct page - set with SETDP */ +static int bbcade; /* GMGM - set for BBC ADE compatibility */ + + +int ext_unary_type(char *s) +{ + if (bbcade) /* GMGM - BBC ADE assembler swaps meaning of < and > */ + return *s=='<' ? HIBYTE : LOBYTE; + return *s=='<' ? LOBYTE : HIBYTE; +} + + +int ext_unary_eval(int type,taddr val,taddr *result,int cnst) +{ + switch (type) { + case LOBYTE: + *result = cnst ? (val & 0xff) : val; + return 1; + case HIBYTE: + *result = cnst ? ((val >> 8) & 0xff) : val; + return 1; + default: + break; + } + return 0; /* unknown type */ +} + + +int ext_find_base(symbol **base,expr *p,section *sec,taddr pc) +{ + /* addr/256 equals >addr, addr%256 and addr&255 equal type==DIV || p->type==MOD) { + if (p->right->type==NUM && p->right->c.val==256) + p->type = p->type == DIV ? HIBYTE : LOBYTE; + } + else if (p->type==BAND && p->right->type==NUM && p->right->c.val==255) + p->type = LOBYTE; + + if (p->type==LOBYTE || p->type==HIBYTE) { + modifier = p->type; + return find_base(p->left,base,sec,pc); + } + return BASE_ILLEGAL; +} + + +int parse_operand(char *p,int len,operand *op,int required) +{ + char *start = p; + int indir = 0; + + p = skip(p); + if (len>0 && required!=DATAOP && check_indir(p,start+len)) { + indir = 1; + p = skip(p+1); + } + + switch (required) { + case IMMED: + if (*p++ != '#') + return PO_NOMATCH; + p = skip(p); + break; + case INDIR: + case INDIRX: + case INDX: + case INDY: + case DPINDIR: + if (!indir) + return PO_NOMATCH; + break; + case WBIT: + if (*p == '#') /* # is optional */ + p = skip(p+1); + default: + if (indir) + return PO_NOMATCH; + break; + } + + op->dp = dpage; + if (required < ACCU) + op->value = parse_expr(&p); + else + op->value = NULL; + + switch (required) { + case INDX: + case INDIRX: + if (*p++ == ',') { + p = skip(p); + if (toupper((unsigned char)*p++) != 'X') + return PO_NOMATCH; + } + else + return PO_NOMATCH; + break; + case ACCU: + if (len != 0) { + if (len!=1 || toupper((unsigned char)*p++) != 'A') + return PO_NOMATCH; + } + break; + case DUMX: + if (toupper((unsigned char)*p++) != 'X') + return PO_NOMATCH; + break; + case DUMY: + if (toupper((unsigned char)*p++) != 'Y') + return PO_NOMATCH; + break; + } + + if (required==INDIR || required==INDX || required==INDY + || required==DPINDIR || required==INDIRX) { + p = skip(p); + if (*p++ != ')') { + cpu_error(2); /* missing closing parenthesis */ + return PO_CORRUPT; + } + } + + p = skip(p); + if (p-start < len) + cpu_error(1); /* trailing garbage in operand */ + op->type = required; + return PO_MATCH; +} + + +char *parse_cpu_special(char *start) +{ + char *name=start,*s=start; + + if (ISIDSTART(*s)) { + s++; + while (ISIDCHAR(*s)) + s++; + + if (s-name==5 && !strnicmp(name,"setdp",5)) { + s = skip(s); + dpage = (utaddr)parse_constexpr(&s); + eol(s); + return skip_line(s); + } + else if (s-name==5 && !strnicmp(name,"zpage",5)) { + char *name; + s = skip(s); + if (name = parse_identifier(&s)) { + symbol *sym = new_import(name); + myfree(name); + sym->flags |= ZPAGESYM; + eol(s); + } + else + cpu_error(8); /* identifier expected */ + return skip_line(s); + } + } + return start; +} + + +static instruction *copy_instruction(instruction *ip) +/* copy an instruction and its operands */ +{ + static instruction newip; + static operand newop[MAX_OPERANDS]; + int i; + + newip.code = ip->code; + + for (i=0; iop[i] != NULL) { + newip.op[i] = &newop[i]; + *newip.op[i] = *ip->op[i]; + } + else + newip.op[i] = NULL; + } + + return &newip; +} + + +static void optimize_instruction(instruction *ip,section *sec, + taddr pc,int final) +{ + mnemonic *mnemo = &mnemonics[ip->code]; + symbol *base; + operand *op; + taddr val; + int i; + + for (i=0; iop[i]) != NULL) { + if (op->value != NULL) { + if (eval_expr(op->value,&val,sec,pc)) + base = NULL; /* val is constant/absolute */ + else + find_base(op->value,&base,sec,pc); /* get base-symbol */ + + if ((op->type==ABS || op->type==ABSX || op->type==ABSY) && + ((base==NULL + && ((val>=0 && val<=0xff) || + ((utaddr)val>=op->dp && (utaddr)val<=op->dp+0xff))) || + (base!=NULL && (base->flags&ZPAGESYM))) + && mnemo->ext.zp_opcode!=0) { + /* we can use a zero page addressing mode for absolute 16-bit */ + op->type += ZPAGE-ABS; + } + else if (op->type==REL && (base==NULL || !is_pc_reloc(base,sec))) { + taddr bd = val - (pc + 2); + + if ((bd<-0x80 || bd>0x7f) && branchopt) { + /* branch dest. out of range: use a B!cc/JMP combination */ + op->type = RELJMP; + } + } + } + } + } +} + + +static size_t get_inst_size(instruction *ip) +{ + size_t sz = 1; + int i; + + for (i=0; iop[i] != NULL) { + switch (ip->op[i]->type) { + case REL: + case INDX: + case INDY: + case DPINDIR: + case IMMED: + case ZPAGE: + case ZPAGEX: + case ZPAGEY: + sz += 1; + break; + case ABS: + case ABSX: + case ABSY: + case INDIR: + case INDIRX: + sz += 2; + break; + case RELJMP: + sz += 4; + break; + } + } + } + return sz; +} + + +size_t instruction_size(instruction *ip,section *sec,taddr pc) +{ + instruction *ipcopy; + int i; + + for (i=0; iop[i]!=NULL && ip->op[i+1]!=NULL) { + if (ip->op[i]->type == ABS) { + if (ip->op[i+1]->type == DUMX) { + ip->op[i]->type = ABSX; + break; + } + else if (ip->op[i+1]->type == DUMY) { + ip->op[i]->type = ABSY; + break; + } + } + else if (ip->op[i]->type == INDIR) { + if (ip->op[i+1]->type == DUMY) { + ip->op[0]->type = INDY; + break; + } + } + } + } + + if (++i < MAX_OPERANDS) { + /* we removed a DUMX/DUMY operand at the end */ + myfree(ip->op[i]); + ip->op[i] = NULL; + } + + ipcopy = copy_instruction(ip); + optimize_instruction(ipcopy,sec,pc,0); + return get_inst_size(ipcopy); +} + + +static void rangecheck(taddr val,operand *op) +{ + switch (op->type) { + case ZPAGE: + case ZPAGEX: + case ZPAGEY: + case INDX: + case INDY: + case DPINDIR: + if ((utaddr)val>=op->dp && (utaddr)val<=op->dp+0xff) + break; + case IMMED: + if (val<-0x80 || val>0xff) + cpu_error(5,8); /* operand doesn't fit into 8-bits */ + break; + case REL: + if (val<-0x80 || val>0x7f) + cpu_error(6); /* branch destination out of range */ + break; + case WBIT: + if (val<0 || val>7) + cpu_error(7); /* illegal bit number */ + break; + } +} + + +dblock *eval_instruction(instruction *ip,section *sec,taddr pc) +{ + dblock *db = new_dblock(); + unsigned char *d,oc; + int optype,i; + taddr val; + + optimize_instruction(ip,sec,pc,1); /* really execute optimizations now */ + + db->size = get_inst_size(ip); + d = db->data = mymalloc(db->size); + + /* write opcode */ + oc = mnemonics[ip->code].ext.opcode; + for (i=0; iop[i]!=NULL ? ip->op[i]->type : IMPLIED; + switch (optype) { + case ZPAGE: + case ZPAGEX: + case ZPAGEY: + oc = mnemonics[ip->code].ext.zp_opcode; + break; + case RELJMP: + oc ^= 0x20; /* B!cc branch */ + break; + } + } + *d++ = oc; + + for (i=0; iop[i] != NULL){ + operand *op = ip->op[i]; + int offs = d - db->data; + symbol *base; + + optype = (int)op->type; + if (op->value != NULL) { + if (!eval_expr(op->value,&val,sec,pc)) { + modifier = 0; + if (optype!=WBIT && find_base(op->value,&base,sec,pc) == BASE_OK) { + if (optype==REL && !is_pc_reloc(base,sec)) { + /* relative branch requires no relocation */ + val = val - (pc + offs + 1); + } + else { + int type = REL_ABS; + int size; + rlist *rl; + + switch (optype) { + case ABS: + case ABSX: + case ABSY: + case INDIR: + case INDIRX: + size = 16; + break; + case INDX: + case INDY: + case DPINDIR: + case ZPAGE: + case ZPAGEX: + case ZPAGEY: + case IMMED: + size = 8; + break; + case RELJMP: + size = 16; + offs = 3; + break; + case REL: + type = REL_PC; + size = 8; + break; + default: + ierror(0); + break; + } + + rl = add_extnreloc(&db->relocs,base,val,type,0,size,offs); + switch (modifier) { + case LOBYTE: + if (rl) + ((nreloc *)rl->reloc)->mask = 0xff; + val = val & 0xff; + break; + case HIBYTE: + if (rl) + ((nreloc *)rl->reloc)->mask = 0xff00; + val = (val >> 8) & 0xff; + break; + } + } + } + else + general_error(38); /* illegal relocation */ + } + else { + /* constant/absolute value */ + if (optype == REL) + val = val - (pc + offs + 1); + } + + rangecheck(val,op); + + /* write operand data */ + switch (optype) { + case ABSX: + case ABSY: + if (!*(db->data)) /* STX/STY allow only ZeroPage addressing mode */ + cpu_error(5,8); /* operand doesn't fit into 8 bits */ + case ABS: + case INDIR: + case INDIRX: + *d++ = val & 0xff; + *d++ = (val>>8) & 0xff; + break; + case DPINDIR: + case INDX: + case INDY: + case ZPAGE: + case ZPAGEX: + case ZPAGEY: + if ((utaddr)val>=op->dp && (utaddr)val<=op->dp+0xff) + val -= op->dp; + case IMMED: + case REL: + *d++ = val & 0xff; + break; + case RELJMP: + if (d - db->data > 1) + ierror(0); + *d++ = 3; /* B!cc *+3 */ + *d++ = 0x4c; /* JMP */ + *d++ = val & 0xff; + *d++ = (val>>8) & 0xff; + break; + case WBIT: + *(db->data) |= (val&7) << 4; /* set bit number in opcode */ + break; + } + } + } + } + + return db; +} + + +dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc) +{ + dblock *db = new_dblock(); + taddr val; + + if (bitsize!=8 && bitsize!=16 && bitsize!=32) + cpu_error(3,bitsize); /* data size not supported */ + + db->size = bitsize >> 3; + db->data = mymalloc(db->size); + if (!eval_expr(op->value,&val,sec,pc)) { + symbol *base; + int btype; + rlist *rl; + + modifier = 0; + btype = find_base(op->value,&base,sec,pc); + if (btype==BASE_OK || (btype==BASE_PCREL && modifier==0)) { + rl = add_extnreloc(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS,0,bitsize,0); + switch (modifier) { + case LOBYTE: + if (rl) + ((nreloc *)rl->reloc)->mask = 0xff; + val = val & 0xff; + break; + case HIBYTE: + if (rl) + ((nreloc *)rl->reloc)->mask = 0xff00; + val = (val >> 8) & 0xff; + break; + } + } + else if (btype != BASE_NONE) + general_error(38); /* illegal relocation */ + } + if (bitsize < 16) { + if (val<-0x80 || val>0xff) + cpu_error(5,8); /* operand doesn't fit into 8-bits */ + } else if (bitsize < 32) { + if (val<-0x8000 || val>0xffff) + cpu_error(5,16); /* operand doesn't fit into 16-bits */ + } + + setval(0,db->data,db->size,val); + return db; +} + + +operand *new_operand() +{ + operand *new = mymalloc(sizeof(*new)); + new->type = -1; + return new; +} + + +int cpu_available(int idx) +{ + return (mnemonics[idx].ext.available & cpu_type) != 0; +} + + +int init_cpu() +{ + return 1; +} + + +int cpu_args(char *p) +{ + if (!strcmp(p,"-opt-branch")) + branchopt = 1; + else if (!strcmp(p,"-bbcade")) /* GMGM */ + bbcade = 1; + else if (!strcmp(p,"-illegal")) + cpu_type |= ILL; + else if (!strcmp(p,"-dtv")) + cpu_type |= DTV; + else if (!strcmp(p,"-c02")) + cpu_type = M6502 | M65C02; + else if (!strcmp(p,"-wdc02")) + cpu_type = M6502 | M65C02 | WDC02; + else if (!strcmp(p,"-ce02")) + cpu_type = M6502 | M65C02 | WDC02 | CSGCE02; + else if (!strcmp(p,"-6280")) + cpu_type = M6502 | M65C02 | WDC02 | HU6280; + else + return 0; + + return 1; +} diff --git a/vasm-1/cpus/6502/cpu.h b/vasm-1/cpus/6502/cpu.h new file mode 100644 index 0000000..98a6f90 --- /dev/null +++ b/vasm-1/cpus/6502/cpu.h @@ -0,0 +1,96 @@ +/* +** cpu.h 650x/65C02/6510/6280 cpu-description header-file +** (c) in 2002,2008,2009,2014,2018,2020 by Frank Wille +*/ + +#define BIGENDIAN 0 +#define LITTLEENDIAN 1 +#define VASM_CPU_650X 1 + +/* maximum number of operands for one mnemonic */ +#define MAX_OPERANDS 3 + +/* maximum number of mnemonic-qualifiers per mnemonic */ +#define MAX_QUALIFIERS 0 + +/* data type to represent a target-address */ +typedef int32_t taddr; +typedef uint32_t utaddr; + +/* minimum instruction alignment */ +#define INST_ALIGN 1 + +/* default alignment for n-bit data */ +#define DATA_ALIGN(n) 1 + +/* operand class for n-bit data definitions */ +#define DATA_OPERAND(n) DATAOP + +/* returns true when instruction is valid for selected cpu */ +#define MNEMONIC_VALID(i) cpu_available(i) + +/* we define two additional unary operations, '<' and '>' */ +int ext_unary_type(char *); +int ext_unary_eval(int,taddr,taddr *,int); +int ext_find_base(symbol **,expr *,section *,taddr); +#define LOBYTE (LAST_EXP_TYPE+1) +#define HIBYTE (LAST_EXP_TYPE+2) +#define EXT_UNARY_NAME(s) (*s=='<'||*s=='>') +#define EXT_UNARY_TYPE(s) ext_unary_type(s) +#define EXT_UNARY_EVAL(t,v,r,c) ext_unary_eval(t,v,r,c) +#define EXT_FIND_BASE(b,e,s,p) ext_find_base(b,e,s,p) + +/* type to store each operand */ +typedef struct { + int type; + expr *value; + utaddr dp; +} operand; + + +/* additional mnemonic data */ +typedef struct { + unsigned char opcode; + unsigned char zp_opcode; /* !=0 means optimization to zero page allowed */ + uint16_t available; +} mnemonic_extension; + +/* available */ +#define M6502 1 /* standard 6502 instruction set */ +#define ILL 2 /* illegal 6502 instructions */ +#define DTV 4 /* C64 DTV instruction set extension */ +#define M65C02 8 /* basic 65C02 extensions on 6502 instruction set */ +#define WDC02 16 /* WDC65C02 extensions on 65C02 instruction set */ +#define CSGCE02 32 /* CSG65CE02 extensions on WDC65C02 instruction set */ +#define HU6280 64 /* HuC6280 extensions on WDC65C02 instruction set */ + + +/* adressing modes */ +#define IMPLIED 0 +#define ABS 1 /* $1234 */ +#define ABSX 2 /* $1234,X */ +#define ABSY 3 /* $1234,Y */ +#define INDIR 4 /* ($1234) - JMP only */ +#define INDX 5 /* ($12,X) */ +#define INDY 6 /* ($12),Y */ +#define DPINDIR 7 /* ($12) */ +#define INDIRX 8 /* ($1234,X) - JMP only */ +#define ZPAGE 9 /* add ZPAGE-ABS to optimize ABS/ABSX/ABSY */ +#define ZPAGEX 10 +#define ZPAGEY 11 +#define RELJMP 12 /* B!cc/JMP construction */ +#define REL 13 /* $1234 - 8-bit signed relative branch */ +#define IMMED 14 /* #$12 */ +#define WBIT 15 /* bit-number (WDC65C02) */ +#define DATAOP 16 /* data operand */ +#define ACCU 17 /* A */ +#define DUMX 18 /* dummy X as 'second' operand */ +#define DUMY 19 /* dummy Y as 'second' operand */ + + +/* cpu-specific symbol-flags */ +#define ZPAGESYM (RSRVD_C<<0) /* symbol will reside in the zero/direct-page */ + + +/* exported by cpu.c */ +int cpu_available(int); diff --git a/vasm-1/cpus/6502/cpu_errors.h b/vasm-1/cpus/6502/cpu_errors.h new file mode 100644 index 0000000..56c2bd3 --- /dev/null +++ b/vasm-1/cpus/6502/cpu_errors.h @@ -0,0 +1,9 @@ + "instruction not supported on selected architecture",ERROR, + "trailing garbage in operand",WARNING, + "missing closing parenthesis in addressing mode",ERROR, + "data size %d not supported",ERROR, + "relocation does not allow hi/lo modifier",ERROR, + "operand doesn't fit into %d bits",ERROR, /* 05 */ + "branch destination out of range",ERROR, + "illegal bit number",ERROR, + "identifier expected",ERROR, diff --git a/vasm-1/cpus/6502/opcodes.h b/vasm-1/cpus/6502/opcodes.h new file mode 100644 index 0000000..058b338 --- /dev/null +++ b/vasm-1/cpus/6502/opcodes.h @@ -0,0 +1,287 @@ + "adc", {IMMED , }, {0x69,0x00,M6502}, + "adc", {ABS , }, {0x6d,0x65,M6502}, + "adc", {INDX , }, {0x61,0x00,M6502}, + "adc", {DPINDIR, }, {0x72,0x00,M65C02}, + "adc", {INDIR ,DUMY }, {0x71,0x00,M6502}, + "adc", {ABS ,DUMX }, {0x7d,0x75,M6502}, + "adc", {ABS ,DUMY }, {0x79,0x00,M6502}, + "ahx", {INDIR ,DUMY }, {0x93,0x00,ILL}, + "ahx", {ABS ,DUMY }, {0x9f,0x00,ILL}, + "alr", {IMMED , }, {0x4b,0x00,ILL}, + "anc", {IMMED , }, {0x0b,0x00,ILL}, + "anc2", {IMMED , }, {0x2b,0x00,ILL}, + "and", {IMMED , }, {0x29,0x00,M6502}, + "and", {ABS , }, {0x2d,0x25,M6502}, + "and", {INDX , }, {0x21,0x00,M6502}, + "and", {DPINDIR, }, {0x32,0x00,M65C02}, + "and", {INDIR ,DUMY }, {0x31,0x00,M6502}, + "and", {ABS ,DUMX }, {0x3d,0x35,M6502}, + "and", {ABS ,DUMY }, {0x39,0x00,M6502}, + "arr", {IMMED , }, {0x6b,0x00,ILL}, + "asl", {ACCU , }, {0x0a,0x00,M6502}, + "asl", {ABS , }, {0x0e,0x06,M6502}, + "asl", {IMPLIED, }, {0x0a,0x00,M6502}, + "asl", {ABS ,DUMX }, {0x1e,0x16,M6502}, + "aso", {ABS , }, {0x0f,0x07,ILL}, + "aso", {INDX , }, {0x03,0x00,ILL}, + "aso", {INDIR ,DUMY }, {0x13,0x00,ILL}, + "aso", {ABS ,DUMX }, {0x1f,0x17,ILL}, + "aso", {ABS ,DUMY }, {0x1b,0x00,ILL}, + "axa", {INDIR ,DUMY }, {0x93,0x00,ILL}, + "axa", {ABS ,DUMY }, {0x9f,0x00,ILL}, + "axs", {IMMED , }, {0xcb,0x00,ILL}, + "axs", {ABS , }, {0x8f,0x87,ILL}, + "axs", {INDX , }, {0x83,0x00,ILL}, + "axs", {ABS ,DUMY }, {0x00,0x97,ILL}, + "bbr", {WBIT ,ZPAGE ,REL }, {0x00,0x0f,WDC02}, + "bbr0", {ZPAGE ,REL }, {0x00,0x0f,WDC02}, + "bbr1", {ZPAGE ,REL }, {0x00,0x1f,WDC02}, + "bbr2", {ZPAGE ,REL }, {0x00,0x2f,WDC02}, + "bbr3", {ZPAGE ,REL }, {0x00,0x3f,WDC02}, + "bbr4", {ZPAGE ,REL }, {0x00,0x4f,WDC02}, + "bbr5", {ZPAGE ,REL }, {0x00,0x5f,WDC02}, + "bbr6", {ZPAGE ,REL }, {0x00,0x6f,WDC02}, + "bbr7", {ZPAGE ,REL }, {0x00,0x7f,WDC02}, + "bbs", {WBIT ,ZPAGE ,REL }, {0x00,0x8f,WDC02}, + "bbs0", {ZPAGE ,REL }, {0x00,0x8f,WDC02}, + "bbs1", {ZPAGE ,REL }, {0x00,0x9f,WDC02}, + "bbs2", {ZPAGE ,REL }, {0x00,0xaf,WDC02}, + "bbs3", {ZPAGE ,REL }, {0x00,0xbf,WDC02}, + "bbs4", {ZPAGE ,REL }, {0x00,0xcf,WDC02}, + "bbs5", {ZPAGE ,REL }, {0x00,0xdf,WDC02}, + "bbs6", {ZPAGE ,REL }, {0x00,0xef,WDC02}, + "bbs7", {ZPAGE ,REL }, {0x00,0xff,WDC02}, + "bcc", {REL , }, {0x90,0x00,M6502}, + "bcs", {REL , }, {0xb0,0x00,M6502}, + "beq", {REL , }, {0xf0,0x00,M6502}, + "bit", {IMMED , }, {0x89,0x00,M65C02}, + "bit", {ABS , }, {0x2c,0x24,M6502}, + "bit", {ABS ,DUMX }, {0x3c,0x34,M65C02}, + "bmi", {REL , }, {0x30,0x00,M6502}, + "bne", {REL , }, {0xd0,0x00,M6502}, + "bpl", {REL , }, {0x10,0x00,M6502}, + "bra", {REL , }, {0x12,0x00,DTV}, + "bra", {REL , }, {0x80,0x00,M65C02}, + "brk", {IMPLIED, }, {0x00,0x00,M6502}, + "bsr", {REL , }, {0x44,0x00,HU6280}, + "bvc", {REL , }, {0x50,0x00,M6502}, + "bvs", {REL , }, {0x70,0x00,M6502}, + "cla", {IMPLIED, }, {0x62,0x00,HU6280}, + "clc", {IMPLIED, }, {0x18,0x00,M6502}, + "cld", {IMPLIED, }, {0xd8,0x00,M6502}, + "cli", {IMPLIED, }, {0x58,0x00,M6502}, + "clv", {IMPLIED, }, {0xb8,0x00,M6502}, + "clx", {IMPLIED, }, {0x82,0x00,HU6280}, + "cly", {IMPLIED, }, {0xc2,0x00,HU6280}, + "cmp", {IMMED , }, {0xc9,0x00,M6502}, + "cmp", {ABS , }, {0xcd,0xc5,M6502}, + "cmp", {INDX , }, {0xc1,0x00,M6502}, + "cmp", {DPINDIR, }, {0xd2,0x00,M65C02}, + "cmp", {INDIR ,DUMY }, {0xd1,0x00,M6502}, + "cmp", {ABS ,DUMX }, {0xdd,0xd5,M6502}, + "cmp", {ABS ,DUMY }, {0xd9,0x00,M6502}, + "cpx", {IMMED , }, {0xe0,0x00,M6502}, + "cpx", {ABS , }, {0xec,0xe4,M6502}, + "cpy", {IMMED , }, {0xc0,0x00,M6502}, + "cpy", {ABS , }, {0xcc,0xc4,M6502}, + "csh", {IMPLIED, }, {0xd4,0x00,HU6280}, + "csl", {IMPLIED, }, {0x54,0x00,HU6280}, + "dcm", {ABS , }, {0xcf,0xc7,ILL}, + "dcm", {INDX , }, {0xc3,0x00,ILL}, + "dcm", {INDIR ,DUMY }, {0xd3,0x00,ILL}, + "dcm", {ABS ,DUMX }, {0xdf,0xd7,ILL}, + "dcm", {ABS ,DUMY }, {0xdb,0x00,ILL}, + "dcp", {ABS , }, {0xcf,0xc7,ILL}, + "dcp", {INDX , }, {0xc3,0x00,ILL}, + "dcp", {INDIR ,DUMY }, {0xd3,0x00,ILL}, + "dcp", {ABS ,DUMX }, {0xdf,0xd7,ILL}, + "dcp", {ABS ,DUMY }, {0xdb,0x00,ILL}, + "dea", {IMPLIED, }, {0x3a,0x00,M65C02}, + "dec", {ACCU , }, {0x3a,0x00,M65C02}, + "dec", {IMPLIED, }, {0x3a,0x00,M65C02}, + "dec", {ABS , }, {0xce,0xc6,M6502}, + "dec", {ABS ,DUMX }, {0xde,0xd6,M6502}, + "dex", {IMPLIED, }, {0xca,0x00,M6502}, + "dey", {IMPLIED, }, {0x88,0x00,M6502}, + "eor", {IMMED , }, {0x49,0x00,M6502}, + "eor", {ABS , }, {0x4d,0x45,M6502}, + "eor", {INDX , }, {0x41,0x00,M6502}, + "eor", {DPINDIR, }, {0x52,0x00,M65C02}, + "eor", {INDIR ,DUMY }, {0x51,0x00,M6502}, + "eor", {ABS ,DUMX }, {0x5d,0x55,M6502}, + "eor", {ABS ,DUMY }, {0x59,0x00,M6502}, + "ina", {IMPLIED, }, {0x1a,0x00,M65C02}, + "inc", {ACCU , }, {0x1a,0x00,M65C02}, + "inc", {IMPLIED, }, {0x1a,0x00,M65C02}, + "inc", {ABS , }, {0xee,0xe6,M6502}, + "inc", {ABS ,DUMX }, {0xfe,0xf6,M6502}, + "ins", {ABS , }, {0xef,0xe7,ILL}, + "ins", {INDX , }, {0xe3,0x00,ILL}, + "ins", {INDIR ,DUMY }, {0xf3,0x00,ILL}, + "ins", {ABS ,DUMX }, {0xff,0xf7,ILL}, + "ins", {ABS ,DUMY }, {0xfb,0x00,ILL}, + "inx", {IMPLIED, }, {0xe8,0x00,M6502}, + "iny", {IMPLIED, }, {0xc8,0x00,M6502}, + "isc", {ABS , }, {0xef,0xe7,ILL}, + "isc", {INDX , }, {0xe3,0x00,ILL}, + "isc", {INDIR ,DUMY }, {0xf3,0x00,ILL}, + "isc", {ABS ,DUMX }, {0xff,0xf7,ILL}, + "isc", {ABS ,DUMY }, {0xfb,0x00,ILL}, + "jmp", {ABS , }, {0x4c,0x00,M6502}, + "jmp", {INDIRX , }, {0x7c,0x00,M65C02}, + "jmp", {INDIR , }, {0x6c,0x00,M6502}, + "jsr", {ABS , }, {0x20,0x00,M6502}, + "las", {ABS ,DUMY }, {0xbb,0x00,ILL}, + "lax", {IMMED , }, {0xab,0x00,ILL}, + "lax", {ABS , }, {0xaf,0xa7,ILL}, + "lax", {ABS ,DUMY }, {0xbf,0xb7,ILL}, + "lax", {INDX , }, {0xa3,0x00,ILL}, + "lax", {INDIR ,DUMY }, {0xb3,0x00,ILL}, + "lda", {IMMED , }, {0xa9,0x00,M6502}, + "lda", {ABS , }, {0xad,0xa5,M6502}, + "lda", {INDX , }, {0xa1,0x00,M6502}, + "lda", {DPINDIR, }, {0xb2,0x00,M65C02}, + "lda", {INDIR ,DUMY }, {0xb1,0x00,M6502}, + "lda", {ABS ,DUMX }, {0xbd,0xb5,M6502}, + "lda", {ABS ,DUMY }, {0xb9,0x00,M6502}, + "ldx", {IMMED , }, {0xa2,0x00,M6502}, + "ldx", {ABS , }, {0xae,0xa6,M6502}, + "ldx", {ABS ,DUMY }, {0xbe,0xb6,M6502}, + "ldy", {IMMED , }, {0xa0,0x00,M6502}, + "ldy", {ABS , }, {0xac,0xa4,M6502}, + "ldy", {ABS ,DUMX }, {0xbc,0xb4,M6502}, + "lse", {ABS , }, {0x4f,0x47,ILL}, + "lse", {INDX , }, {0x43,0x00,ILL}, + "lse", {INDIR ,DUMY }, {0x53,0x00,ILL}, + "lse", {ABS ,DUMX }, {0x5f,0x57,ILL}, + "lse", {ABS ,DUMY }, {0x5b,0x00,ILL}, + "lsr", {ACCU , }, {0x4a,0x00,M6502}, + "lsr", {ABS , }, {0x4e,0x46,M6502}, + "lsr", {IMPLIED, }, {0x4a,0x00,M6502}, + "lsr", {ABS ,DUMX }, {0x5e,0x56,M6502}, + "nop", {IMPLIED, }, {0xea,0x00,M6502}, + "oal", {IMMED , }, {0xab,0x00,ILL}, + "ora", {IMMED , }, {0x09,0x00,M6502}, + "ora", {ABS , }, {0x0d,0x05,M6502}, + "ora", {INDX , }, {0x01,0x00,M6502}, + "ora", {DPINDIR, }, {0x12,0x00,M65C02}, + "ora", {INDIR ,DUMY }, {0x11,0x00,M6502}, + "ora", {ABS ,DUMX }, {0x1d,0x15,M6502}, + "ora", {ABS ,DUMY }, {0x19,0x00,M6502}, + "pha", {IMPLIED, }, {0x48,0x00,M6502}, + "php", {IMPLIED, }, {0x08,0x00,M6502}, + "phx", {IMPLIED, }, {0xda,0x00,M65C02}, + "phy", {IMPLIED, }, {0x5a,0x00,M65C02}, + "pla", {IMPLIED, }, {0x68,0x00,M6502}, + "plp", {IMPLIED, }, {0x28,0x00,M6502}, + "plx", {IMPLIED, }, {0xfa,0x00,M65C02}, + "ply", {IMPLIED, }, {0x7a,0x00,M65C02}, + "rla", {ABS , }, {0x2f,0x27,ILL}, + "rla", {INDX , }, {0x23,0x00,ILL}, + "rla", {INDIR ,DUMY }, {0x33,0x00,ILL}, + "rla", {ABS ,DUMX }, {0x3f,0x37,ILL}, + "rla", {ABS ,DUMY }, {0x3b,0x00,ILL}, + "rmb", {WBIT ,ZPAGE }, {0x00,0x07,WDC02}, + "rmb0", {ZPAGE }, {0x00,0x07,WDC02}, + "rmb1", {ZPAGE }, {0x00,0x17,WDC02}, + "rmb2", {ZPAGE }, {0x00,0x27,WDC02}, + "rmb3", {ZPAGE }, {0x00,0x37,WDC02}, + "rmb4", {ZPAGE }, {0x00,0x47,WDC02}, + "rmb5", {ZPAGE }, {0x00,0x57,WDC02}, + "rmb6", {ZPAGE }, {0x00,0x67,WDC02}, + "rmb7", {ZPAGE }, {0x00,0x77,WDC02}, + "rol", {ACCU , }, {0x2a,0x00,M6502}, + "rol", {ABS , }, {0x2e,0x26,M6502}, + "rol", {IMPLIED, }, {0x2a,0x00,M6502}, + "rol", {ABS ,DUMX }, {0x3e,0x36,M6502}, + "ror", {ACCU , }, {0x6a,0x00,M6502}, + "ror", {ABS , }, {0x6e,0x66,M6502}, + "ror", {IMPLIED, }, {0x6a,0x00,M6502}, + "ror", {ABS ,DUMX }, {0x7e,0x76,M6502}, + "rra", {ABS , }, {0x6f,0x67,ILL}, + "rra", {INDX , }, {0x63,0x00,ILL}, + "rra", {INDIR ,DUMY }, {0x73,0x00,ILL}, + "rra", {ABS ,DUMX }, {0x7f,0x77,ILL}, + "rra", {ABS ,DUMY }, {0x7b,0x00,ILL}, + "rti", {IMPLIED, }, {0x40,0x00,M6502}, + "rts", {IMPLIED, }, {0x60,0x00,M6502}, + "sac", {IMMED , }, {0x32,0x00,DTV}, + "sax", {IMMED , }, {0xcb,0x00,ILL}, + "sax", {ABS , }, {0x8f,0x87,ILL}, + "sax", {INDX , }, {0x83,0x00,ILL}, + "sax", {ABS ,DUMY }, {0x00,0x97,ILL}, + "sax", {IMPLIED, }, {0x22,0x00,HU6280}, + "say", {ABS ,DUMX }, {0x9c,0x00,ILL}, + "say", {IMPLIED, }, {0x42,0x00,HU6280}, + "sbc", {IMMED , }, {0xe9,0x00,M6502}, + "sbc", {ABS , }, {0xed,0xe5,M6502}, + "sbc", {INDX , }, {0xe1,0x00,M6502}, + "sbc", {DPINDIR, }, {0xf2,0x00,M65C02}, + "sbc", {INDIR ,DUMY }, {0xf1,0x00,M6502}, + "sbc", {ABS ,DUMX }, {0xfd,0xf5,M6502}, + "sbc", {ABS ,DUMY }, {0xf9,0x00,M6502}, + "sbc2", {IMMED , }, {0xeb,0x00,ILL}, + "sec", {IMPLIED, }, {0x38,0x00,M6502}, + "sed", {IMPLIED, }, {0xf8,0x00,M6502}, + "sei", {IMPLIED, }, {0x78,0x00,M6502}, + "set", {IMPLIED, }, {0xf4,0x00,HU6280}, + "shx", {ABS ,DUMY }, {0x9e,0x00,ILL}, + "shy", {ABS ,DUMX }, {0x9c,0x00,ILL}, + "sir", {IMMED , }, {0x42,0x00,DTV}, + "slo", {ABS , }, {0x0f,0x07,ILL}, + "slo", {INDX , }, {0x03,0x00,ILL}, + "slo", {INDIR ,DUMY }, {0x13,0x00,ILL}, + "slo", {ABS ,DUMX }, {0x1f,0x17,ILL}, + "slo", {ABS ,DUMY }, {0x1b,0x00,ILL}, + "smb", {WBIT ,ZPAGE }, {0x00,0x87,WDC02}, + "smb0", {ZPAGE }, {0x00,0x87,WDC02}, + "smb1", {ZPAGE }, {0x00,0x97,WDC02}, + "smb2", {ZPAGE }, {0x00,0xa7,WDC02}, + "smb3", {ZPAGE }, {0x00,0xb7,WDC02}, + "smb4", {ZPAGE }, {0x00,0xc7,WDC02}, + "smb5", {ZPAGE }, {0x00,0xd7,WDC02}, + "smb6", {ZPAGE }, {0x00,0xe7,WDC02}, + "smb7", {ZPAGE }, {0x00,0xf7,WDC02}, + "sre", {ABS , }, {0x4f,0x47,ILL}, + "sre", {INDX , }, {0x43,0x00,ILL}, + "sre", {INDIR ,DUMY }, {0x53,0x00,ILL}, + "sre", {ABS ,DUMX }, {0x5f,0x57,ILL}, + "sre", {ABS ,DUMY }, {0x5b,0x00,ILL}, + "st0", {IMMED , }, {0x03,0x00,HU6280}, + "st1", {IMMED , }, {0x13,0x00,HU6280}, + "st2", {IMMED , }, {0x23,0x00,HU6280}, + "sta", {ABS , }, {0x8d,0x85,M6502}, + "sta", {INDX , }, {0x81,0x00,M6502}, + "sta", {DPINDIR, }, {0x92,0x00,M65C02}, + "sta", {INDIR ,DUMY }, {0x91,0x00,M6502}, + "sta", {ABS ,DUMX }, {0x9d,0x95,M6502}, + "sta", {ABS ,DUMY }, {0x99,0x00,M6502}, + "stp", {IMPLIED, }, {0xdb,0x00,WDC02}, + "stx", {ABS , }, {0x8e,0x86,M6502}, + "stx", {ABS ,DUMY }, {0x00,0x96,M6502}, + "sty", {ABS , }, {0x8c,0x84,M6502}, + "sty", {ABS ,DUMX }, {0x00,0x94,M6502}, + "stz", {ABS , }, {0x9c,0x64,M65C02}, + "stz", {ABS ,DUMX }, {0x9e,0x74,M65C02}, + "sxy", {IMPLIED, }, {0x02,0x00,HU6280}, + "tai", {ABS ,ABS ,ABS }, {0xf3,0x00,HU6280}, + "tam", {IMMED , }, {0x53,0x00,HU6280}, + "tas", {ABS ,DUMY }, {0x9b,0x00,ILL}, + "tax", {IMPLIED, }, {0xaa,0x00,M6502}, + "tay", {IMPLIED, }, {0xa8,0x00,M6502}, + "tdd", {ABS ,ABS ,ABS }, {0xc3,0x00,HU6280}, + "tia", {ABS ,ABS ,ABS }, {0xe3,0x00,HU6280}, + "tii", {ABS ,ABS ,ABS }, {0x73,0x00,HU6280}, + "tin", {ABS ,ABS ,ABS }, {0xd3,0x00,HU6280}, + "tma", {IMMED , }, {0x43,0x00,HU6280}, + "trb", {ABS , }, {0x1c,0x14,M65C02}, + "tsb", {ABS , }, {0x0c,0x04,M65C02}, + "tst", {IMMED ,ABS }, {0x93,0x83,HU6280}, + "tst", {IMMED ,ABS ,DUMX }, {0xb3,0xa3,HU6280}, + "tsx", {IMPLIED, }, {0xba,0x00,M6502}, + "txa", {IMPLIED, }, {0x8a,0x00,M6502}, + "txs", {IMPLIED, }, {0x9a,0x00,M6502}, + "tya", {IMPLIED, }, {0x98,0x00,M6502}, + "wai", {IMPLIED, }, {0xcb,0x00,WDC02}, + "xaa", {IMMED , }, {0x8b,0x00,ILL}, + "xas", {ABS ,DUMY }, {0x9e,0x00,ILL}, diff --git a/vasm-1/cpus/6800/cpu.c b/vasm-1/cpus/6800/cpu.c new file mode 100644 index 0000000..bb248d8 --- /dev/null +++ b/vasm-1/cpus/6800/cpu.c @@ -0,0 +1,398 @@ +/* + * cpu.c 6800 cpu description file + * (c) in 2013-2016,2019 by Esben Norby and Frank Wille + */ + +#include "vasm.h" + +mnemonic mnemonics[] = { +#include "opcodes.h" +}; + +int mnemonic_cnt = sizeof(mnemonics) / sizeof(mnemonics[0]); + +int bitsperbyte = 8; +int bytespertaddr = 2; +char * cpu_copyright = "vasm 6800/6801/68hc11 cpu backend 0.4 (c) 2013-2016,2019 Esben Norby"; +char * cpuname = "6800"; + +static uint8_t cpu_type = M6800; +static int modifier; /* set by find_base() */ + + +int +init_cpu() +{ + return 1; +} + + +int +cpu_args(char *p) +{ + if (!strncmp(p, "-m68", 4)) { + p += 4; + if (p[0] == '0' && p[3] == '\0') { + switch(p[1]) { + case '0': + case '2': + case '8': + /* 6802 and 6808 are a 6800 with embedded ROM/RAM */ + cpu_type = M6800; + break; + case '1': + case '3': + /* 6803 is a 6801 with embedded ROM/RAM */ + cpu_type = M6801; + break; + default: + /* 6804 and 6805 are not opcode compatible + * 6809 is somewhat compatible, but not completely + * 6806 and 6807 do not exist, to my knowledge + */ + return 0; + } + } else if (!stricmp(p, "hc11")) + cpu_type = M68HC11; + else + return 0; + return 1; + } + return 0; +} + + +char * +parse_cpu_special(char *start) +{ + return start; +} + + +operand * +new_operand() +{ + operand *new = mymalloc(sizeof(*new)); + new->type = -1; + return new; +} + + +int +parse_operand(char *p, int len, operand *op, int required) +{ + char *start = p; + + op->value = NULL; + + switch (required) { + case IMM: + case IMM16: + if (*p++ != '#') + return PO_NOMATCH; + p = skip(p); + /* fall through */ + case REL: + case DATAOP: + op->value = parse_expr(&p); + break; + + case ADDR: + if (*p == '<') { + required = DIR; + p++; + } + else if (*p == '>') { + required = EXT; + p++; + } + op->value = parse_expr(&p); + break; + + case DIR: + if (*p == '>') + return PO_NOMATCH; + else if (*p == '<') + p++; + op->value = parse_expr(&p); + break; + + case EXT: + if (*p == '<') + return PO_NOMATCH; + else if (*p == '>') + p++; + op->value = parse_expr(&p); + break; + + case REGX: + if (toupper((unsigned char)*p++) != 'X') + return PO_NOMATCH; + break; + case REGY: + if (toupper((unsigned char)*p++) != 'Y') + return PO_NOMATCH; + break; + + default: + return PO_NOMATCH; + } + + op->type = required; + return PO_MATCH; +} + + +static size_t +eval_oper(operand *op, section *sec, taddr pc, taddr offs, dblock *db) +{ + size_t size = 0; + symbol *base = NULL; + int btype; + taddr val; + + if (op->value != NULL && !eval_expr(op->value, &val, sec, pc)) { + modifier = 0; + btype = find_base(op->value, &base, sec, pc); + } + + switch (op->type) { + case ADDR: + if (base != NULL || val < 0 || val > 0xff) { + op->type = EXT; + size = 2; + } + else { + op->type = DIR; + size = 1; + } + break; + case DIR: + size = 1; + if (db != NULL && (val < 0 || val > 0xff)) + cpu_error(1); /* operand doesn't fit into 8-bits */ + break; + case IMM: + size = 1; + if (db != NULL && !modifier && (val < -0x80 || val > 0xff)) + cpu_error(1); /* operand doesn't fit into 8-bits */ + break; + case EXT: + case IMM16: + size = 2; + break; + case REL: + size = 1; + break; + } + + if (size > 0 && db != NULL) { + /* create relocation entry and code for this operand */ + if (op->type == REL && base == NULL) { + /* relative branch to absolute label */ + val = val - (pc + offs + 1); + if (val < -0x80 || val > 0x7f) + cpu_error(2); /* branch out of range */ + } + else if (op->type == REL && base != NULL && btype == BASE_OK) { + /* relative branches */ + if (!is_pc_reloc(base, sec)) { + val = val - (pc + offs + 1); + if (val < -0x80 || val > 0x7f) + cpu_error(2); /* branch out of range */ + } + else + add_extnreloc(&db->relocs, base, val, REL_PC, + 0, 8, offs); + } + else if (base != NULL && btype != BASE_ILLEGAL) { + rlist *rl; + + rl = add_extnreloc(&db->relocs, base, val, + btype==BASE_PCREL? REL_PC : REL_ABS, + 0, size << 3, offs); + switch (modifier) { + case LOBYTE: + if (rl) ((nreloc *)rl->reloc)->mask = 0xff; + val &= 0xff; + break; + case HIBYTE: + if (rl) ((nreloc *)rl->reloc)->mask = 0xff00; + val = (val >> 8) & 0xff; + break; + } + } + else if (base != NULL) + general_error(38); /* illegal relocation */ + + if (size == 1) { + op->code[0] = val & 0xff; + } + else if (size == 2) { + op->code[0] = (val >> 8) & 0xff; + op->code[1] = val & 0xff; + } + else + ierror(0); + } + return (size); +} + + +size_t +instruction_size(instruction *ip, section *sec, taddr pc) +{ + operand op; + int i; + size_t size; + + size = (mnemonics[ip->code].ext.prebyte != 0) ? 2 : 1; + + for (i = 0; i < MAX_OPERANDS && ip->op[i] != NULL; i++) { + op = *(ip->op[i]); + size += eval_oper(&op, sec, pc, size, NULL); + } + + return (size); +} + + +dblock * +eval_instruction(instruction *ip, section *sec, taddr pc) +{ + dblock *db = new_dblock(); + uint8_t opcode; + uint8_t *d; + int i; + size_t size; + + /* evaluate operands and determine instruction size */ + opcode = mnemonics[ip->code].ext.opcode; + size = (mnemonics[ip->code].ext.prebyte != 0) ? 2 : 1; + for (i = 0; i < MAX_OPERANDS && ip->op[i] != NULL; i++) { + size += eval_oper(ip->op[i], sec, pc, size, db); + if (ip->op[i]->type == DIR) + opcode = mnemonics[ip->code].ext.dir_opcode; + } + + /* allocate and fill data block */ + db->size = size; + d = db->data = mymalloc(size); + + if (mnemonics[ip->code].ext.prebyte != 0) + *d++ = mnemonics[ip->code].ext.prebyte; + *d++ = opcode; + + /* write operands */ + for (i = 0; i < MAX_OPERANDS && ip->op[i] != NULL; i++) { + switch (ip->op[i]->type) { + case IMM: + case DIR: + case REL: + *d++ = ip->op[i]->code[0]; + break; + case IMM16: + case EXT: + *d++ = ip->op[i]->code[0]; + *d++ = ip->op[i]->code[1]; + break; + } + } + + return (db); +} + +dblock * +eval_data(operand *op, size_t bitsize, section *sec, taddr pc) +{ + dblock *db = new_dblock(); + uint8_t *d; + taddr val; + + if (bitsize != 8 && bitsize != 16) + cpu_error(0,bitsize); /* data size not supported */ + + db->size = bitsize >> 3; + d = db->data = mymalloc(db->size); + + if (!eval_expr(op->value, &val, sec, pc)) { + symbol *base; + int btype; + rlist *rl; + + modifier = 0; + btype = find_base(op->value, &base, sec, pc); + if (btype==BASE_OK || (btype==BASE_PCREL && modifier==0)) { + rl = add_extnreloc(&db->relocs, base, val, + btype==BASE_PCREL ? REL_PC : REL_ABS, + 0, bitsize, 0); + switch (modifier) { + case LOBYTE: + if (rl) ((nreloc *)rl->reloc)->mask = 0xff; + val &= 0xff; + break; + case HIBYTE: + if (rl) ((nreloc *)rl->reloc)->mask = 0xff00; + val = (val >> 8) & 0xff; + break; + } + } + else if (btype != BASE_NONE) + general_error(38); /* illegal relocation */ + } + + if (bitsize == 8) { + if (val < -0x80 || val > 0xff) + cpu_error(1); /* operand doesn't fit into 8-bits */ + } + else /* 16 bits */ + *d++ = (val >> 8) & 0xff; + *d = val & 0xff; + + return (db); +} + + +int +ext_unary_eval(int type, taddr val, taddr *result, int cnst) +{ + switch (type) { + case LOBYTE: + *result = cnst ? (val & 0xff) : val; + return 1; + case HIBYTE: + *result = cnst ? ((val >> 8) & 0xff) : val; + return 1; + default: + break; + } + + return 0; /* unknown type */ +} + + +int +ext_find_base(symbol **base, expr *p, section *sec, taddr pc) +{ + /* addr/256 equals >addr, addr%256 and addr&255 equal type==DIV || p->type==MOD) { + if (p->right->type==NUM && p->right->c.val==256) + p->type = p->type == DIV ? HIBYTE : LOBYTE; + } + else if (p->type==BAND && p->right->type==NUM && p->right->c.val==255) + p->type = LOBYTE; + + if (p->type==LOBYTE || p->type==HIBYTE) { + modifier = p->type; + return find_base(p->left,base,sec,pc); + } + + return BASE_ILLEGAL; +} + + +int +cpu_available(int idx) +{ + return (mnemonics[idx].ext.available & cpu_type) != 0; +} diff --git a/vasm-1/cpus/6800/cpu.h b/vasm-1/cpus/6800/cpu.h new file mode 100644 index 0000000..69c739a --- /dev/null +++ b/vasm-1/cpus/6800/cpu.h @@ -0,0 +1,80 @@ +/* + * cpu.h 6800 cpu description file + * (c) in 2013-2014 by Esben Norby and Frank Wille +*/ + +#define BIGENDIAN 1 +#define LITTLEENDIAN 0 +#define VASM_CPU_6800 1 + +/* maximum number of operands for one mnemonic */ +#define MAX_OPERANDS 4 + +/* maximum number of mnemonic-qualifiers per mnemonic */ +#define MAX_QUALIFIERS 0 + +/* data type to represent a target-address */ +typedef int16_t taddr; +typedef uint16_t utaddr; + +/* minimum instruction alignment */ +#define INST_ALIGN 1 + +/* default alignment for n-bit data */ +#define DATA_ALIGN(n) 1 + +/* operand class for n-bit data definitions */ +#define DATA_OPERAND(n) DATAOP + +/* returns true when instruction is valid for selected cpu */ +#define MNEMONIC_VALID(i) cpu_available(i) + +/* allow commas and blanks at the same time to separate instruction operands */ +#define OPERSEP_COMMA 1 +#define OPERSEP_BLANK 1 + +/* we define two additional unary operations, '<' and '>' */ +int ext_unary_eval(int,taddr,taddr *,int); +int ext_find_base(symbol **,expr *,section *,taddr); +#define LOBYTE (LAST_EXP_TYPE+1) +#define HIBYTE (LAST_EXP_TYPE+2) +#define EXT_UNARY_NAME(s) (*s=='<'||*s=='>') +#define EXT_UNARY_TYPE(s) (*s=='<'?LOBYTE:HIBYTE) +#define EXT_UNARY_EVAL(t,v,r,c) ext_unary_eval(t,v,r,c) +#define EXT_FIND_BASE(b,e,s,p) ext_find_base(b,e,s,p) + +/* type to store each operand */ +typedef struct { + uint16_t type; + uint8_t code[2]; + expr *value; +} operand; + + +/* additional mnemonic data */ +typedef struct { + unsigned char prebyte; + unsigned char opcode; + unsigned char dir_opcode; /* !=0 means optimization to DIR allowed */ + uint8_t available; +} mnemonic_extension; + +/* available */ +#define M6800 1 +#define M6801 2 /* 6801/6803: Adds D register and some extras */ +#define M68HC11 4 /* standard 68HC11 instruction set */ + +/* adressing modes */ +#define INH 0 +#define IMM 1 /* #$12 */ /* IMM ii */ +#define IMM16 2 /* #$1234 */ /* IMM jj kk */ +#define ADDR 3 +#define EXT 4 /* EXT hh */ +#define DIR 5 /* DIR dd */ +#define REL 6 /* REL rr */ +#define REGX 7 +#define REGY 8 +#define DATAOP 9 /* data operand */ + +/* exported by cpu.c */ +int cpu_available(int); diff --git a/vasm-1/cpus/6800/cpu_errors.h b/vasm-1/cpus/6800/cpu_errors.h new file mode 100644 index 0000000..f752cc0 --- /dev/null +++ b/vasm-1/cpus/6800/cpu_errors.h @@ -0,0 +1,3 @@ + "data size %d not supported",ERROR, + "operand doesn't fit into 8-bits",ERROR, + "branch destination out of range",ERROR, diff --git a/vasm-1/cpus/6800/opcodes.h b/vasm-1/cpus/6800/opcodes.h new file mode 100644 index 0000000..7ffb13a --- /dev/null +++ b/vasm-1/cpus/6800/opcodes.h @@ -0,0 +1,339 @@ + "aba", {INH }, {0x00, 0x1B, 0x00, M6800|M6801|M68HC11}, + "abx", {INH }, {0x00, 0x3A, 0x00, M6801|M68HC11}, + "aby", {INH }, {0x18, 0x3A, 0x00, M68HC11}, + "adca", {IMM }, {0x00, 0x89, 0x00, M6800|M6801|M68HC11}, + "adca", {ADDR }, {0x00, 0xB9, 0x99, M6800|M6801|M68HC11}, + "adca", {DIR, REGX }, {0x00, 0x00, 0xA9, M6800|M6801|M68HC11}, + "adca", {DIR, REGY }, {0x18, 0x00, 0xA9, M68HC11}, + "adcb", {IMM }, {0x00, 0xC9, 0x00, M6800|M6801|M68HC11}, + "adcb", {ADDR }, {0x00, 0xF9, 0xD9, M6800|M6801|M68HC11}, + "adcb", {DIR, REGX }, {0x00, 0x00, 0xE9, M6800|M6801|M68HC11}, + "adcb", {DIR, REGY }, {0x18, 0x00, 0xE9, M68HC11}, + "adda", {IMM }, {0x00, 0x8B, 0x00, M6800|M6801|M68HC11}, + "adda", {ADDR }, {0x00, 0xBB, 0x9B, M6800|M6801|M68HC11}, + "adda", {DIR, REGX }, {0x00, 0x00, 0xAB, M6800|M6801|M68HC11}, + "adda", {DIR, REGY }, {0x18, 0x00, 0xAB, M68HC11}, + "addb", {IMM }, {0x00, 0xCB, 0x00, M6800|M6801|M68HC11}, + "addb", {ADDR }, {0x00, 0xFB, 0xDB, M6800|M6801|M68HC11}, + "addb", {DIR, REGX }, {0x00, 0x00, 0xEB, M6800|M6801|M68HC11}, + "addb", {DIR, REGY }, {0x18, 0x00, 0xEB, M68HC11}, + "addd", {IMM16 }, {0x00, 0xC3, 0x00, M6801|M68HC11}, + "addd", {ADDR }, {0x00, 0xF3, 0xD3, M6801|M68HC11}, + "addd", {DIR, REGX }, {0x00, 0x00, 0xE3, M6801|M68HC11}, + "addd", {DIR, REGY }, {0x18, 0x00, 0xE3, M68HC11}, + "anda", {IMM }, {0x00, 0x84, 0x00, M6800|M6801|M68HC11}, + "anda", {ADDR }, {0x00, 0xB4, 0x94, M6800|M6801|M68HC11}, + "anda", {DIR, REGX }, {0x00, 0x00, 0xA4, M6800|M6801|M68HC11}, + "anda", {DIR, REGY }, {0x18, 0x00, 0xA4, M68HC11}, + "andb", {IMM }, {0x00, 0xC4, 0x00, M6800|M6801|M68HC11}, + "andb", {ADDR }, {0x00, 0xF4, 0xD4, M6800|M6801|M68HC11}, + "andb", {DIR, REGX }, {0x00, 0x00, 0xE4, M6800|M6801|M68HC11}, + "andb", {DIR, REGY }, {0x18, 0x00, 0xE4, M68HC11}, + "asl", {EXT }, {0x00, 0x78, 0x00, M6800|M6801|M68HC11}, + "asl", {DIR, REGX }, {0x00, 0x00, 0x68, M6800|M6801|M68HC11}, + "asl", {DIR, REGY }, {0x18, 0x00, 0x68, M68HC11}, + "asla", {INH }, {0x00, 0x48, 0x00, M6800|M6801|M68HC11}, + "aslb", {INH }, {0x00, 0x58, 0x00, M6800|M6801|M68HC11}, + "asld", {INH }, {0x00, 0x05, 0x00, M6800|M6801|M68HC11}, + "asr", {EXT }, {0x00, 0x77, 0x00, M6800|M6801|M68HC11}, + "asr", {DIR, REGX }, {0x00, 0x00, 0x67, M6800|M6801|M68HC11}, + "asr", {DIR, REGY }, {0x18, 0x00, 0x67, M68HC11}, + "asra", {INH, }, {0x00, 0x47, 0x00, M6800|M6801|M68HC11}, + "asrb", {INH, }, {0x00, 0x57, 0x00, M6800|M6801|M68HC11}, + + "bclr", {DIR, IMM }, {0x00, 0x00, 0x15, M68HC11}, + "bclr", {DIR, REGX, IMM }, {0x00, 0x00, 0x1D, M68HC11}, + "bclr", {DIR, REGY, IMM }, {0x18, 0x00, 0x1D, M68HC11}, + + "bcc", {REL, }, {0x00, 0x24, 0x00, M6800|M6801|M68HC11}, + "bcs", {REL, }, {0x00, 0x25, 0x00, M6800|M6801|M68HC11}, + "beq", {REL, }, {0x00, 0x27, 0x00, M6800|M6801|M68HC11}, + "bge", {REL, }, {0x00, 0x2C, 0x00, M6800|M6801|M68HC11}, + "bgt", {REL, }, {0x00, 0x2E, 0x00, M6800|M6801|M68HC11}, + "bhi", {REL, }, {0x00, 0x22, 0x00, M6800|M6801|M68HC11}, + "bhs", {REL, }, {0x00, 0x24, 0x00, M6800|M6801|M68HC11}, + "bita", {IMM }, {0x00, 0x85, 0x00, M6800|M6801|M68HC11}, + "bita", {ADDR, }, {0x00, 0xB5, 0x95, M6800|M6801|M68HC11}, + "bita", {DIR, REGX }, {0x00, 0x00, 0xA5, M6800|M6801|M68HC11}, + "bita", {DIR, REGY }, {0x18, 0x00, 0xA5, M68HC11}, + "bitb", {IMM }, {0x00, 0xC5, 0x00, M6800|M6801|M68HC11}, + "bitb", {ADDR, }, {0x00, 0xF5, 0xD5, M6800|M6801|M68HC11}, + "bitb", {DIR, REGX }, {0x00, 0x00, 0xE5, M6800|M6801|M68HC11}, + "bitb", {DIR, REGY }, {0x18, 0x00, 0xE5, M68HC11}, + + "ble", {REL, }, {0x00, 0x2F, 0x00, M6800|M6801|M68HC11}, + "blo", {REL, }, {0x00, 0x25, 0x00, M6800|M6801|M68HC11}, + "bls", {REL, }, {0x00, 0x23, 0x00, M6800|M6801|M68HC11}, + "blt", {REL, }, {0x00, 0x2D, 0x00, M6800|M6801|M68HC11}, + "bmi", {REL, }, {0x00, 0x2B, 0x00, M6800|M6801|M68HC11}, + "bne", {REL, }, {0x00, 0x26, 0x00, M6800|M6801|M68HC11}, + "bpl", {REL, }, {0x00, 0x2A, 0x00, M6800|M6801|M68HC11}, + "bra", {REL, }, {0x00, 0x20, 0x00, M6800|M6801|M68HC11}, + "jr", {REL, }, {0x00, 0x20, 0x00, M6800|M6801|M68HC11}, /* bra */ + + "brclr",{DIR, IMM, REL }, {0x00, 0x00, 0x13, M68HC11}, + "brclr",{DIR, REGX, IMM, REL}, {0x00, 0x00, 0x1F, M68HC11}, + "brclr",{DIR, REGY, IMM, REL}, {0x18, 0x00, 0x1F, M68HC11}, + + "brn", {REL, }, {0x00, 0x21, 0x00, M6801|M68HC11}, + + "brset",{DIR, IMM, REL }, {0x00, 0x00, 0x12, M68HC11}, + "brset",{DIR, REGX, IMM, REL}, {0x00, 0x00, 0x1E, M68HC11}, + "brset",{DIR, REGY, IMM, REL}, {0x18, 0x00, 0x1E, M68HC11}, + + "bset", {DIR, IMM }, {0x00, 0x00, 0x14, M68HC11}, + "bset", {DIR, REGX, IMM }, {0x00, 0x00 ,0x1C, M68HC11}, + "bset", {DIR, REGY, IMM }, {0x18, 0x00 ,0x1C, M68HC11}, + + "bsr", {REL, }, {0x00, 0x8D, 0x00, M6800|M6801|M68HC11}, + "callr",{REL, }, {0x00, 0x8D, 0x00, M6800|M6801|M68HC11}, /* bsr */ + "bvc", {REL, }, {0x00, 0x28, 0x00, M6800|M6801|M68HC11}, + "bvs", {REL, }, {0x00, 0x29, 0x00, M6800|M6801|M68HC11}, + "cba", {INH, }, {0x00, 0x11, 0x00, M6800|M6801|M68HC11}, + "clc", {INH, }, {0x00, 0x0C, 0x00, M6800|M6801|M68HC11}, + "cli", {INH, }, {0x00, 0x0E, 0x00, M6800|M6801|M68HC11}, + "ei", {INH, }, {0x00, 0x0E, 0x00, M6800|M6801|M68HC11}, /* cli */ + "clr", {EXT, }, {0x00, 0x7F, 0x00, M6800|M6801|M68HC11}, + "clr", {DIR, REGX }, {0x00, 0x00, 0x6F, M6800|M6801|M68HC11}, + "clr", {DIR, REGY }, {0x18, 0x00, 0x6F, M68HC11}, + "clra", {INH, }, {0x00, 0x4F, 0x00, M6800|M6801|M68HC11}, + "clrb", {INH, }, {0x00, 0x5F, 0x00, M6800|M6801|M68HC11}, + "clv", {INH, }, {0x00, 0x0A, 0x00, M6800|M6801|M68HC11}, + "cmpa", {IMM }, {0x00, 0x81, 0x00, M6800|M6801|M68HC11}, + "cmpa", {ADDR, }, {0x00, 0xB1, 0x91, M6800|M6801|M68HC11}, + "cmpa", {DIR, REGX }, {0x00, 0x00, 0xA1, M6800|M6801|M68HC11}, + "cmpa", {DIR, REGY }, {0x18, 0x00, 0xA1, M68HC11}, + "cmpb", {IMM }, {0x00, 0xC1, 0x00, M6800|M6801|M68HC11}, + "cmpb", {ADDR, }, {0x00, 0xF1, 0xD1, M6800|M6801|M68HC11}, + "cmpb", {DIR, REGX }, {0x00, 0x00, 0xE1, M6800|M6801|M68HC11}, + "cmpb", {DIR, REGY }, {0x18, 0x00, 0xE1, M68HC11}, + "com", {EXT, }, {0x00, 0x73, 0x00, M6800|M6801|M68HC11}, + "com", {DIR, REGX }, {0x00, 0x00, 0x63, M6800|M6801|M68HC11}, + "com", {DIR, REGY }, {0x18, 0x00, 0x63, M68HC11}, + "coma", {INH, }, {0x00, 0x43, 0x00, M6800|M6801|M68HC11}, + "comb", {INH, }, {0x00, 0x53, 0x00, M6800|M6801|M68HC11}, + "cpd", {IMM16 }, {0x1A, 0x83, 0x00, M68HC11}, + "cpd", {ADDR, }, {0x1A, 0xB3, 0x93, M68HC11}, + "cpd", {DIR, REGX }, {0x1A, 0x00, 0xA3, M68HC11}, + "cpd", {DIR, REGY }, {0xCD, 0x00, 0xA3, M68HC11}, + "cmpd", {IMM16 }, {0x1A, 0x83, 0x00, M68HC11}, /* cpd */ + "cmpd", {ADDR, }, {0x1A, 0xB3, 0x93, M68HC11}, /* cpd */ + "cmpd", {DIR, REGX }, {0x1A, 0x00, 0xA3, M68HC11}, /* cpd */ + "cmpd", {DIR, REGY }, {0xCD, 0x00, 0xA3, M68HC11}, /* cpd */ + "cpx", {IMM16 }, {0x00, 0x8C, 0x00, M6800|M6801|M68HC11}, + "cpx", {ADDR, }, {0x00, 0xBC, 0x9C, M6800|M6801|M68HC11}, + "cpx", {DIR, REGX }, {0x00, 0x00, 0xAC, M6800|M6801|M68HC11}, + "cpx", {DIR, REGY }, {0xCD, 0x00, 0xAC, M68HC11}, + "cmpx", {IMM16 }, {0x00, 0x8C, 0x00, M6800|M6801|M68HC11}, /* cpx */ + "cmpx", {ADDR, }, {0x00, 0xBC, 0x9C, M6800|M6801|M68HC11}, /* cpx */ + "cmpx", {DIR, REGX }, {0x00, 0x00, 0xAC, M6800|M6801|M68HC11}, /* cpx */ + "cmpx", {DIR, REGY }, {0xCD, 0x00, 0xAC, M68HC11}, /* cpx */ + "cpy", {IMM16 }, {0x18, 0x8C, 0x00, M68HC11}, + "cpy", {ADDR, }, {0x18, 0xBC, 0x9C, M68HC11}, + "cpy", {DIR, REGX }, {0x1A, 0x00, 0xAC, M68HC11}, + "cpy", {DIR, REGY }, {0x18, 0x00, 0xAC, M68HC11}, + "cmpy", {IMM16 }, {0x18, 0x8C, 0x00, M68HC11}, /* cpy */ + "cmpy", {ADDR, }, {0x18, 0xBC, 0x9C, M68HC11}, /* cpy */ + "cmpy", {DIR, REGX }, {0x1A, 0x00, 0xAC, M68HC11}, /* cpy */ + "cmpy", {DIR, REGY }, {0x18, 0x00, 0xAC, M68HC11}, /* cpy */ + "daa", {INH, }, {0x00, 0x19, 0x00, M6800|M6801|M68HC11}, + "dec", {EXT, }, {0x00, 0x7A, 0x00, M6800|M6801|M68HC11}, + "dec", {DIR, REGX }, {0x00, 0x00, 0x6A, M6800|M6801|M68HC11}, + "dec", {DIR, REGY }, {0x18, 0x00, 0x6A, M68HC11}, + "deca", {INH, }, {0x00, 0x4A, 0x00, M6800|M6801|M68HC11}, + "decb", {INH, }, {0x00, 0x5A, 0x00, M6800|M6801|M68HC11}, + "des", {INH, }, {0x00, 0x34, 0x00, M6800|M6801|M68HC11}, + "decs", {INH, }, {0x00, 0x34, 0x00, M6800|M6801|M68HC11}, /* des */ + "dex", {INH, }, {0x00, 0x09, 0x00, M6800|M6801|M68HC11}, + "decx", {INH, }, {0x00, 0x09, 0x00, M6800|M6801|M68HC11}, /* dex */ + "dey", {INH, }, {0x18, 0x09, 0x00, M68HC11}, + "decy", {INH, }, {0x18, 0x09, 0x00, M68HC11}, /* dey */ + "eora", {IMM, }, {0x00, 0x88, 0x00, M6800|M6801|M68HC11}, + "eora", {ADDR, }, {0x00, 0xB8, 0x98, M6800|M6801|M68HC11}, + "eora", {DIR, REGX }, {0x00, 0x00, 0xA8, M6800|M6801|M68HC11}, + "eora", {DIR, REGY }, {0x18, 0x00, 0xA8, M68HC11}, + "xora", {IMM, }, {0x00, 0x88, 0x00, M6800|M6801|M68HC11}, /* eora */ + "xora", {ADDR, }, {0x00, 0xB8, 0x98, M6800|M6801|M68HC11}, /* eora */ + "xora", {DIR, REGX }, {0x00, 0x00, 0xA8, M6800|M6801|M68HC11}, /* eora */ + "xora", {DIR, REGY }, {0x18, 0x00, 0xA8, M68HC11}, /* eora */ + "eorb", {IMM, }, {0x00, 0xC8, 0x00, M6800|M6801|M68HC11}, + "eorb", {ADDR, }, {0x00, 0xF8, 0xD8, M6800|M6801|M68HC11}, + "eorb", {DIR, REGX }, {0x00, 0x00, 0xE8, M6800|M6801|M68HC11}, + "eorb", {DIR, REGY }, {0x18, 0x00, 0xE8, M68HC11}, + "xorb", {IMM, }, {0x00, 0xC8, 0x00, M6800|M6801|M68HC11}, /* eorb */ + "xorb", {ADDR, }, {0x00, 0xF8, 0xD8, M6800|M6801|M68HC11}, /* eorb */ + "xorb", {DIR, REGX }, {0x00, 0x00, 0xE8, M6800|M6801|M68HC11}, /* eorb */ + "xorb", {DIR, REGY }, {0x18, 0x00, 0xE8, M68HC11}, /* eorb */ + "fdiv", {INH, }, {0x00, 0x03, 0x00, M68HC11}, + "idiv", {INH, }, {0x00, 0x02, 0x00, M68HC11}, + "inc", {EXT, }, {0x00, 0x7C, 0x00, M6800|M6801|M68HC11}, + "inc", {DIR, REGX }, {0x00, 0x00, 0x6C, M6800|M6801|M68HC11}, + "inc", {DIR, REGY }, {0x18, 0x00, 0x6C, M68HC11}, + "inca", {INH, }, {0x00, 0x4C, 0x00, M6800|M6801|M68HC11}, + "incb", {INH, }, {0x00, 0x5C, 0x00, M6800|M6801|M68HC11}, + "ins", {INH, }, {0x00, 0x31, 0x00, M6800|M6801|M68HC11}, + "incs", {INH, }, {0x00, 0x31, 0x00, M6800|M6801|M68HC11}, /* ins */ + "inx", {INH, }, {0x00, 0x08, 0x00, M6800|M6801|M68HC11}, + "incx", {INH, }, {0x00, 0x08, 0x00, M6800|M6801|M68HC11}, /* inx */ + "iny", {INH, }, {0x18, 0x08, 0x00, M68HC11}, + "incy", {INH, }, {0x18, 0x08, 0x00, M68HC11}, /* iny */ + "jmp", {EXT, }, {0x00, 0x7E, 0x00, M6800|M6801|M68HC11}, + "jmp", {DIR, REGX }, {0x00, 0x00, 0x6E, M6800|M6801|M68HC11}, + "jmp", {DIR, REGY }, {0x18, 0x00, 0x6E, M68HC11}, + "jsr", {ADDR, }, {0x00, 0xBD, 0x9D, M6800|M6801|M68HC11}, + "jsr", {DIR, REGX }, {0x00, 0x00, 0xAD, M6800|M6801|M68HC11}, + "jsr", {DIR, REGY }, {0x18, 0x00, 0xAD, M68HC11}, + "call", {ADDR, }, {0x00, 0xBD, 0x9D, M6800|M6801|M68HC11}, /* jsr */ + "call", {DIR, REGX }, {0x00, 0x00, 0xAD, M6800|M6801|M68HC11}, /* jsr */ + "call", {DIR, REGY }, {0x18, 0x00, 0xAD, M68HC11}, /* jsr */ + "lda", {IMM, }, {0x00, 0x86, 0x00, M6800|M6801|M68HC11}, + "lda", {ADDR, }, {0x00, 0xB6, 0x96, M6800|M6801|M68HC11}, + "lda", {DIR, REGX }, {0x00, 0x00, 0xA6, M6800|M6801|M68HC11}, + "lda", {DIR, REGY }, {0x18, 0x00, 0xA6, M68HC11}, + "ldaa", {IMM, }, {0x00, 0x86, 0x00, M6800|M6801|M68HC11}, + "ldaa", {ADDR, }, {0x00, 0xB6, 0x96, M6800|M6801|M68HC11}, + "ldaa", {DIR, REGX }, {0x00, 0x00, 0xA6, M6800|M6801|M68HC11}, + "ldaa", {DIR, REGY }, {0x18, 0x00, 0xA6, M68HC11}, + "ldb", {IMM, }, {0x00, 0xC6, 0x00, M6800|M6801|M68HC11}, + "ldb", {ADDR, }, {0x00, 0xF6, 0xD6, M6800|M6801|M68HC11}, + "ldb", {DIR, REGX }, {0x00, 0x00, 0xE6, M6800|M6801|M68HC11}, + "ldb", {DIR, REGY }, {0x18, 0x00, 0xE6, M68HC11}, + "ldab", {IMM, }, {0x00, 0xC6, 0x00, M6800|M6801|M68HC11}, + "ldab", {ADDR, }, {0x00, 0xF6, 0xD6, M6800|M6801|M68HC11}, + "ldab", {DIR, REGX }, {0x00, 0x00, 0xE6, M6800|M6801|M68HC11}, + "ldab", {DIR, REGY }, {0x18, 0x00, 0xE6, M68HC11}, + "ldd", {IMM16, }, {0x00, 0xCC, 0x00, M6801|M68HC11}, + "ldd", {ADDR, }, {0x00, 0xFC, 0xDC, M6801|M68HC11}, + "ldd", {DIR, REGX }, {0x00, 0x00, 0xEC, M6801|M68HC11}, + "ldd", {DIR, REGY }, {0x18, 0x00, 0xEC, M68HC11}, + "lds", {IMM16, }, {0x00, 0x8E, 0x00, M6800|M6801|M68HC11}, + "lds", {ADDR, }, {0x00, 0xBE, 0x9E, M6800|M6801|M68HC11}, + "lds", {DIR, REGX }, {0x00, 0x00, 0xAE, M6800|M6801|M68HC11}, + "lds", {DIR, REGY }, {0x18, 0x00, 0xAE, M68HC11}, + "ldx", {IMM16, }, {0x00, 0xCE, 0x00, M6800|M6801|M68HC11}, + "ldx", {ADDR, }, {0x00, 0xFE, 0xDE, M6800|M6801|M68HC11}, + "ldx", {DIR, REGX }, {0x00, 0x00, 0xEE, M6800|M6801|M68HC11}, + "ldx", {DIR, REGY }, {0xCD, 0x00, 0xEE, M68HC11}, + "ldy", {IMM16, }, {0x18, 0xCE, 0x00, M68HC11}, + "ldy", {ADDR, }, {0x18, 0xFE, 0xDE, M68HC11}, + "ldy", {DIR, REGX }, {0x1A, 0x00, 0xEE, M68HC11}, + "ldy", {DIR, REGY }, {0x18, 0x00, 0xEE, M68HC11}, + "lsl", {EXT, }, {0x00, 0x78, 0x00, M6800|M6801|M68HC11}, + "lsl", {DIR, REGX }, {0x00, 0x00, 0x68, M6800|M6801|M68HC11}, + "lsl", {DIR, REGY }, {0x18, 0x00, 0x68, M68HC11}, + "lsla", {INH, }, {0x00, 0x48, 0x00, M6800|M6801|M68HC11}, + "lslb", {INH, }, {0x00, 0x58, 0x00, M6800|M6801|M68HC11}, + "lsld", {INH, }, {0x00, 0x05, 0x00, M6801|M68HC11}, + "lsr", {EXT, }, {0x00, 0x74, 0x00, M6800|M6801|M68HC11}, + "lsr", {DIR, REGX }, {0x00, 0x00, 0x64, M6800|M6801|M68HC11}, + "lsr", {DIR, REGY }, {0x18, 0x00, 0x64, M68HC11}, + "lsra", {INH, }, {0x00, 0x44, 0x00, M6800|M6801|M68HC11}, + "lsrb", {INH, }, {0x00, 0x54, 0x00, M6800|M6801|M68HC11}, + "lsrd", {INH, }, {0x00, 0x04, 0x00, M6801|M68HC11}, + "mul", {INH, }, {0x00, 0x3D, 0x00, M6801|M68HC11}, + "neg", {EXT, }, {0x00, 0x70, 0x00, M6800|M6801|M68HC11}, + "neg", {DIR, REGX }, {0x00, 0x00, 0x60, M6800|M6801|M68HC11}, + "neg", {DIR, REGY }, {0x18, 0x00, 0x60, M68HC11}, + "nega", {INH, }, {0x00, 0x40, 0x00, M6800|M6801|M68HC11}, + "negb", {INH, }, {0x00, 0x50, 0x00, M6800|M6801|M68HC11}, + "nop", {INH, }, {0x00, 0x01, 0x00, M6800|M6801|M68HC11}, + "oraa", {IMM, }, {0x00, 0x8A, 0x00, M6800|M6801|M68HC11}, + "oraa", {ADDR, }, {0x00, 0xBA, 0x9A, M6800|M6801|M68HC11}, + "oraa", {DIR, REGX }, {0x00, 0x00, 0xAA, M6800|M6801|M68HC11}, + "oraa", {DIR, REGY }, {0x18, 0x00, 0xAA, M68HC11}, + "orab", {IMM, }, {0x00, 0xCA, 0x00, M6800|M6801|M68HC11}, + "orab", {ADDR, }, {0x00, 0xFA, 0xDA, M6800|M6801|M68HC11}, + "orab", {DIR, REGX }, {0x00, 0x00, 0xEA, M6800|M6801|M68HC11}, + "orab", {DIR, REGY }, {0x18, 0x00, 0xEA, M68HC11}, + "psha", {INH, }, {0x00, 0x36, 0x00, M6800|M6801|M68HC11}, + "pusha",{INH, }, {0x00, 0x36, 0x00, M6800|M6801|M68HC11}, /* psha */ + "pshb", {INH, }, {0x00, 0x37, 0x00, M6800|M6801|M68HC11}, + "pushb",{INH, }, {0x00, 0x37, 0x00, M6800|M6801|M68HC11}, /* pshb */ + "pshx", {INH, }, {0x00, 0x3C, 0x00, M6801|M68HC11}, + "pushx",{INH, }, {0x00, 0x3C, 0x00, M6801|M68HC11}, /* pshx */ + "pshy", {INH, }, {0x18, 0x3C, 0x00, M68HC11}, + "pushy", {INH, }, {0x18, 0x3C, 0x00, M68HC11}, /* pshy */ + "pula", {INH, }, {0x00, 0x32, 0x00, M6800|M6801|M68HC11}, + "popa", {INH, }, {0x00, 0x32, 0x00, M6800|M6801|M68HC11}, /* pula */ + "pulb", {INH, }, {0x00, 0x33, 0x00, M6800|M6801|M68HC11}, + "popb", {INH, }, {0x00, 0x33, 0x00, M6800|M6801|M68HC11}, /* pulb */ + "pulx", {INH, }, {0x00, 0x38, 0x00, M6801|M68HC11}, + "popx", {INH, }, {0x00, 0x38, 0x00, M6801|M68HC11}, /* pulx */ + "puly", {INH, }, {0x18, 0x38, 0x00, M68HC11}, + "popy", {INH, }, {0x18, 0x38, 0x00, M68HC11}, /* puly */ + "rol", {EXT, }, {0x00, 0x79, 0x00, M6800|M6801|M68HC11}, + "rol", {DIR, REGX }, {0x00, 0x00, 0x69, M6800|M6801|M68HC11}, + "rol", {DIR, REGY }, {0x18, 0x00, 0x69, M68HC11}, + "rola", {INH, }, {0x00, 0x49, 0x00, M6800|M6801|M68HC11}, + "rolb", {INH, }, {0x00, 0x59, 0x00, M6800|M6801|M68HC11}, + "ror", {EXT, }, {0x00, 0x76, 0x00, M6800|M6801|M68HC11}, + "ror", {DIR, REGX }, {0x00, 0x00, 0x66, M6800|M6801|M68HC11}, + "ror", {DIR, REGY }, {0x18, 0x00, 0x66, M68HC11}, + "rora", {INH, }, {0x00, 0x46, 0x00, M6800|M6801|M68HC11}, + "rorb", {INH, }, {0x00, 0x56, 0x00, M6800|M6801|M68HC11}, + "rti", {INH, }, {0x00, 0x3B, 0x00, M6800|M6801|M68HC11}, + "reti", {INH, }, {0x00, 0x3B, 0x00, M6800|M6801|M68HC11}, /* rti */ + "rts", {INH, }, {0x00, 0x39, 0x00, M6800|M6801|M68HC11}, + "ret", {INH, }, {0x00, 0x39, 0x00, M6800|M6801|M68HC11}, /* rts */ + "sba", {INH, }, {0x00, 0x10, 0x00, M6800|M6801|M68HC11}, + "sbca", {IMM, }, {0x00, 0x82, 0x00, M6800|M6801|M68HC11}, + "sbca", {ADDR, }, {0x00, 0xB2, 0x92, M6800|M6801|M68HC11}, + "sbca", {DIR, REGX }, {0x00, 0x00, 0xA2, M6800|M6801|M68HC11}, + "sbca", {DIR, REGY }, {0x18, 0x00, 0xA2, M68HC11}, + "sbcb", {IMM, }, {0x00, 0xC2, 0x00, M6800|M6801|M68HC11}, + "sbcb", {ADDR, }, {0x00, 0xF2, 0xD2, M6800|M6801|M68HC11}, + "sbcb", {DIR, REGX }, {0x00, 0x00, 0xE2, M6800|M6801|M68HC11}, + "sbcb", {DIR, REGY }, {0x18, 0x00, 0xE2, M68HC11}, + "sec", {INH, }, {0x00, 0x0D, 0x00, M6800|M6801|M68HC11}, + "sei", {INH, }, {0x00, 0x0F, 0x00, M6800|M6801|M68HC11}, + "di", {INH, }, {0x00, 0x0F, 0x00, M6800|M6801|M68HC11}, /* sei */ + "sev", {INH, }, {0x00, 0x0B, 0x00, M6800|M6801|M68HC11}, + "staa", {ADDR, }, {0x00, 0xB7, 0x97, M6800|M6801|M68HC11}, + "staa", {DIR, REGX }, {0x00, 0x00, 0xA7, M6800|M6801|M68HC11}, + "staa", {DIR, REGY }, {0x18, 0x00, 0xA7, M68HC11}, + "stab", {ADDR, }, {0x00, 0xF7, 0xD7, M6800|M6801|M68HC11}, + "stab", {DIR, REGX }, {0x00, 0x00, 0xE7, M6800|M6801|M68HC11}, + "stab", {DIR, REGY }, {0x18, 0x00, 0xE7, M68HC11}, + "std", {ADDR, }, {0x00, 0xFD, 0xDD, M6801|M68HC11}, + "std", {DIR, REGX }, {0x00, 0x00, 0xED, M6801|M68HC11}, + "std", {DIR, REGY }, {0x18, 0x00, 0xED, M68HC11}, + "stop", {INH, }, {0x00, 0xCF, 0x00, M68HC11}, + "sts", {ADDR, }, {0x00, 0xBF, 0x9F, M6800|M6801|M68HC11}, + "sts", {DIR, REGX }, {0x00, 0x00, 0xAF, M6800|M6801|M68HC11}, + "sts", {DIR, REGY }, {0x18, 0x00, 0xAF, M68HC11}, + "stx", {ADDR, }, {0x00, 0xFF, 0xDF, M6800|M6801|M68HC11}, + "stx", {DIR, REGX }, {0x00, 0x00, 0xEF, M6800|M6801|M68HC11}, + "stx", {DIR, REGY }, {0xCD, 0x00, 0xEF, M68HC11}, + "sty", {ADDR, }, {0x18, 0xFF, 0xDF, M68HC11}, + "sty", {DIR, REGX }, {0x1A, 0x00, 0xEF, M68HC11}, + "sty", {DIR, REGY }, {0x18, 0x00, 0xEF, M68HC11}, + "suba", {IMM, }, {0x00, 0x80, 0x00, M6800|M6801|M68HC11}, + "suba", {ADDR, }, {0x00, 0xB0, 0x90, M6800|M6801|M68HC11}, + "suba", {DIR, REGX }, {0x00, 0x00, 0xA0, M6800|M6801|M68HC11}, + "suba", {DIR, REGY }, {0x18, 0x00, 0xA0, M68HC11}, + "subb", {IMM, }, {0x00, 0xC0, 0x00, M6800|M6801|M68HC11}, + "subb", {ADDR, }, {0x00, 0xF0, 0xD0, M6800|M6801|M68HC11}, + "subb", {DIR, REGX }, {0x00, 0x00, 0xE0, M6800|M6801|M68HC11}, + "subb", {DIR, REGY }, {0x18, 0x00, 0xE0, M68HC11}, + "subd", {IMM16, }, {0x00, 0x83, 0x00, M6801|M68HC11}, + "subd", {ADDR, }, {0x00, 0xB3, 0x93, M6801|M68HC11}, + "subd", {DIR, REGX }, {0x00, 0x00, 0xA3, M6801|M68HC11}, + "subd", {DIR, REGY }, {0x18, 0x00, 0xA3, M68HC11}, + "swi", {INH, }, {0x00, 0x3F, 0x00, M6800|M6801|M68HC11}, + "tab", {INH, }, {0x00, 0x16, 0x00, M6800|M6801|M68HC11}, + "tap", {INH, }, {0x00, 0x06, 0x00, M6800|M6801|M68HC11}, + "tba", {INH, }, {0x00, 0x17, 0x00, M6800|M6801|M68HC11}, + "test", {INH, }, {0x00, 0x00, 0x00, M68HC11}, + "tpa", {INH, }, {0x00, 0x07, 0x00, M6800|M6801|M68HC11}, + "tst", {EXT, }, {0x00, 0x7D, 0x00, M6800|M6801|M68HC11}, + "tst", {DIR, REGX }, {0x00, 0x00, 0x6D, M6800|M6801|M68HC11}, + "tst", {DIR, REGY }, {0x18, 0x00, 0x6D, M68HC11}, + "tsta", {INH, }, {0x00, 0x4D, 0x00, M6800|M6801|M68HC11}, + "tstb", {INH, }, {0x00, 0x5D, 0x00, M6800|M6801|M68HC11}, + "tsx", {INH, }, {0x00, 0x30, 0x00, M6800|M6801|M68HC11}, + "tsy", {INH, }, {0x18, 0x30, 0x00, M68HC11}, + "txs", {INH, }, {0x00, 0x35, 0x00, M6800|M6801|M68HC11}, + "tys", {INH, }, {0x18, 0x35, 0x00, M68HC11}, + "wai", {INH, }, {0x00, 0x3E, 0x00, M6800|M6801|M68HC11}, + "xgdx", {INH, }, {0x00, 0x8F, 0x00, M68HC11}, + "xgdy", {INH, }, {0x18, 0x8F, 0x00, M68HC11}, diff --git a/vasm-1/cpus/arm/cpu.c b/vasm-1/cpus/arm/cpu.c new file mode 100644 index 0000000..cc04514 --- /dev/null +++ b/vasm-1/cpus/arm/cpu.c @@ -0,0 +1,1751 @@ +/* +** cpu.c ARM cpu-description file +** (c) in 2004,2006,2010,2011,2014-2019 by Frank Wille +*/ + +#include "vasm.h" + +mnemonic mnemonics[] = { +#include "opcodes.h" +}; +int mnemonic_cnt = sizeof(mnemonics)/sizeof(mnemonics[0]); + +char *cpu_copyright = "vasm ARM cpu backend 0.4f (c) 2004,2006,2010,2011,2014-2019 Frank Wille"; +char *cpuname = "ARM"; +int bitsperbyte = 8; +int bytespertaddr = 4; + +uint32_t cpu_type = AAANY; +int arm_be_mode = 0; /* Little-endian is default */ +int thumb_mode = 0; /* 1: Thumb instruction set (16 bit) is active */ + +/* options */ +static unsigned char opt_ldrpc = 0; /* LDR r,sym -> ADD / LDR */ +static unsigned char opt_adr = 0; /* ADR r,sym -> ADRL (ADD/ADD|SUB/SUB) */ + +/* constant data */ +static const char *condition_codes = "eqnecsccmiplvsvchilsgeltgtlealnvhsloul"; + +static const char *addrmode_strings[] = { + "da","ia","db","ib", + "fa","fd","ea","ed", + "bt","tb","sb","sh","t","b","h","s","l", + "p",NULL,"" +}; +enum { + AM_DA=0,AM_IA,AM_DB,AM_IB,AM_FA,AM_FD,AM_EA,AM_ED, + AM_BT,AM_TB,AM_SB,AM_SH,AM_T,AM_B,AM_H,AM_S,AM_L, + AM_P,AM_NULL,AM_NONE +}; + +#define NUM_SHIFTTYPES 6 +static const char *shift_strings[NUM_SHIFTTYPES] = { + "LSL","LSR","ASR","ROR","RRX","ASL" +}; + +static int OC_SWP,OC_NOP; +static int elfoutput = 0; /* output will be an ELF object file */ + +static section *last_section = 0; +static int last_data_type = -1; /* for mapping symbol generation */ +#define TYPE_ARM 0 +#define TYPE_THUMB 1 +#define TYPE_DATA 2 + +#define THB_PREFETCH 4 /* prefetch-correction for Thumb-branches */ +#define ARM_PREFETCH 8 /* prefetch-correction for ARM-branches */ + + + +operand *new_operand(void) +{ + return mycalloc(sizeof(operand)); +} + + +int cpu_available(int idx) +{ + return (mnemonics[idx].ext.available & cpu_type) != 0; +} + + +char *parse_cpu_special(char *start) +/* parse cpu-specific directives; return pointer to end of + cpu-specific text */ +{ + char *name=start,*s=start; + + if (ISIDSTART(*s)) { + s++; + while (ISIDCHAR(*s)) + s++; + if (s-name==6 && !strncmp(name,".thumb",6)) { + thumb_mode = 1; + if (inst_alignment > 1) + inst_alignment = 2; + return s; + } + else if (s-name==4 && !strncmp(name,".arm",4)) { + thumb_mode = 0; + if (inst_alignment > 1) + inst_alignment = 4; + return s; + } + } + return start; +} + + +char *parse_instruction(char *s,int *inst_len,char **ext,int *ext_len, + int *ext_cnt) +/* parse instruction and save extension locations */ +{ + char *inst = s; + int cnt = *ext_cnt; + + while (*s && !isspace((unsigned char)*s)) + s++; + + if (thumb_mode) { /* no qualifiers in THUMB code */ + *inst_len = s - inst; + } + + else { /* ARM mode - we might have up to 2 different qualifiers */ + int len = s - inst; + char c = tolower((unsigned char)*inst); + + if (len > 2) { + if (c=='b' && strnicmp(inst,"bic",3) && (len==3 || len==4)) { + *inst_len = len - 2; + } + else if ((c=='u' || c=='s') && + tolower((unsigned char)*(inst+1))=='m' && len>=5) { + *inst_len = 5; + } + else + *inst_len = 3; + len -= *inst_len; + + if (len > 0) { + char *p = inst + *inst_len; + + if (len >= 2) { + const char *cc = condition_codes; + + while (*cc) { + if (!strnicmp(p,cc,2)) + break; + cc += 2; + } + if (*cc) { /* matched against a condition code */ + ext[cnt] = p; + ext_len[cnt++] = 2; + p += 2; + len -= 2; + } + } + if (len >= 1) { + const char **am = addrmode_strings; + + do { + if (len==strlen(*am) && !strnicmp(*am,p,len)) + break; + am++; + } + while (*am); + if (*am!=NULL || (len==1 && tolower((unsigned char)*p)=='s')) { + ext[cnt] = p; + ext_len[cnt++] = len; + } + } + } + else if (len < 0) + ierror(0); + } + else + *inst_len = len; + + *ext_cnt = cnt; + } + + return s; +} + + +int set_default_qualifiers(char **q,int *q_len) +/* fill in pointers to default qualifiers, return number of qualifiers */ +{ + return 0; +} + + +static int parse_reg(char **pp) +/* parse register, return -1 on error */ +{ + char *p = *pp; + char *name = p; + regsym *sym; + + if (ISIDSTART(*p)) { + p++; + while (ISIDCHAR(*p)) + p++; + if (sym = find_regsym_nc(name,p-name)) { + *pp = p; + return sym->reg_num; + } + } + return -1; /* no valid register found */ +} + + +static int parse_reglist(char **pp) +/* parse register-list, return -1 on error */ +{ + int r=0,list=0,lastreg=-1; + char *p = *pp; + char *name; + regsym *sym; + + if (*p++ == '{') { + p = skip(p); + + do { + if (ISIDSTART(*p)) { + name = p++; + while (ISIDCHAR(*p)) + p++; + if (sym = find_regsym_nc(name,p-name)) { + r = sym->reg_num; + if (lastreg >= 0) { /* range-mode? */ + if (lastreg < r) { + r = lastreg; + lastreg = sym->reg_num; + } + for (; r<=lastreg; list |= 1<type = optype; + op->flags = 0; + op->value = NULL; + p = skip(p); + + if (optype == DATA64_OP) { + op->value = parse_expr_huge(&p); + } + + else if (thumb_mode) { + if (ARMOPER(optype)) { /* standard ARM instruction */ + return PO_NOMATCH; + } + + else if (THREGOPER(optype)) { + /* parse a register */ + int r; + + if (optype==TR5IN || optype==TPCPR || optype==TSPPR) { + if (*p++ != '[') + return PO_NOMATCH; + p = skip(p); + } + + if ((r = parse_reg(&p)) < 0) + return PO_NOMATCH; + op->value = number_expr((taddr)r); + + if (optype==TPCRG || optype==TPCPR) { + if (r != 15) + return PO_NOMATCH; + } + else if (optype==TSPRG || optype==TSPPR) { + if (r != 13) + return PO_NOMATCH; + } + else if (optype==THR02 || optype==THR05) { + if (r<8 || r>15) + return PO_NOMATCH; + } + else { + if (r<0 || r>7) + return PO_NOMATCH; + } + if (optype == TR8IN) { + p = skip(p); + if (*p++ != ']') + return PO_NOMATCH; + } + else if (optype == TR10W) { + if (*p++ != '!') + return PO_NOMATCH; + } + } + + else if (THREGLIST(optype)) { + taddr list = parse_reglist(&p); + + if (optype == TRLST) { + if (list & ~0xff) + return PO_NOMATCH; /* only r0-r7 allowed */ + } + else { + if ((list&0x8000) && optype==TRLPC) { + list = list&~0x8000 | 0x100; + } + else if ((list&0x4000) && optype==TRLLR) { + list = list&~0x4000 | 0x100; + } + if (list & ~0x1ff) + return PO_NOMATCH; /* only r0-r7 / pc / lr allowed */ + } + op->value = number_expr(list); + } + + else if (THIMMOPER(optype)) { + if (*p++ != '#') + return PO_NOMATCH; + p = skip(p); + op->value = parse_expr(&p); + + if (THIMMINDIR(optype)) { + p = skip(p); + if (*p++ != ']') + return PO_NOMATCH; + } + } + + else { /* just parse an expression */ + char *q = p; + + /* check that this isn't any other valid operand */ + if (*p=='#' || *p=='[' || *p=='{' || parse_reg(&q)>=0) + return PO_NOMATCH; + op->value = parse_expr(&p); + } + } + + else { /* ARM mode */ + if (THUMBOPER(optype)) { /* Thumb instruction */ + return PO_NOMATCH; + } + + else if (STDOPER(optype)) { + /* parse an expression (register, label, imm.) and assign to 'value' */ + if (IMMEDOPER(optype)) { + if (*p++ != '#') + return PO_NOMATCH; + p = skip(p); + } + else if (optype==R19PR || optype==R19PO) { + if (*p++ != '[') + return PO_NOMATCH; + p = skip(p); + } + + if (UPDOWNOPER(optype)) { + if (*p == '-') { + p = skip(p+1); + } + else { + if (*p == '+') + p = skip(p+1); + op->flags |= OFL_UP; + } + } + + if (REGOPER(optype)) { + int r = parse_reg(&p); + + if (r >= 0) + op->value = number_expr((taddr)r); + else + return PO_NOMATCH; + } + else { /* an expression */ + if (ISIDSTART(*p) || isdigit((unsigned char)*p) || + (!UPDOWNOPER(optype) && (*p=='-' || *p=='+'))) + op->value = parse_expr(&p); + else + return PO_NOMATCH; + } + + if (optype==R19PO || optype==R3UD1 || optype==IMUD1 || optype==IMCP1) { + p = skip(p); + if (*p++ != ']') + return PO_NOMATCH; + } + if (optype==R19WB || optype==R3UD1 || optype==IMUD1 || optype==IMCP1) { + if (*p == '!') { + p++; + op->flags |= OFL_WBACK; + } + } + } + + else if (SHIFTOPER(optype)) { + char *name = p; + int i; + + p = skip_identifier(p); + if (p == NULL) + return PO_NOMATCH; + for (i=0; i= NUM_SHIFTTYPES) + return PO_NOMATCH; + if (i == 4) { + /* RRX is ROR with immediate value 0 */ + op->flags |= OFL_IMMEDSHIFT; + op->value = number_expr(0); + i = 3; /* ROR */ + } + else { + /* parse immediate or register for LSL, LSR, ASR, ROR */ + p = skip(p); + if (i == 5) + i = 0; /* ASL -> LSL */ + if (*p == '#') { + p++; + op->flags |= OFL_IMMEDSHIFT; + op->value = parse_expr(&p); + } + else if (optype == SHIFT) { + int r = parse_reg(&p); + + if (r >= 0) + op->value = number_expr((taddr)r); + else + return PO_NOMATCH; + } + else + return PO_NOMATCH; /* no shift-count in register allowed */ + } + op->flags |= i & OFL_SHIFTOP; + + if (optype == SHIM1) { + /* check for pre-indexed with optional write-back */ + p = skip(p); + if (*p++ != ']') + return PO_NOMATCH; + if (*p == '!') { + p++; + op->flags |= OFL_WBACK; + } + } + } + + else if (optype == CSPSR) { + char *name = p; + + p = skip_identifier(p); + if (p == NULL) + return PO_NOMATCH; + if (!strnicmp(name,"CPSR",p-name)) + op->flags &= ~OFL_SPSR; + else if (!strnicmp(name,"SPSR",p-name)) + op->flags |= OFL_SPSR; + else + return PO_NOMATCH; + op->value = number_expr(0xf); /* all fields f,s,x,c */ + } + + else if (optype == PSR_F) { + char *name = p; + taddr fields = 0xf; + + p = skip_identifier(p); + if (p==NULL || (p-name)<4) + return PO_NOMATCH; + if (!strnicmp(name,"CPSR",4)) + op->flags &= ~OFL_SPSR; + else if (!strnicmp(name,"SPSR",4)) + op->flags |= OFL_SPSR; + else + return PO_NOMATCH; + + if ((p-name)>5 && *(name+4)=='_') { + fields = 0; + name += 5; + while (name < p) { + switch (tolower((unsigned char)*name++)) { + case 'f': fields |= 1; break; + case 's': fields |= 2; break; + case 'x': fields |= 4; break; + case 'c': fields |= 8; break; + default: return PO_NOMATCH; + } + } + } + else if ((p-name) > 4) + return PO_NOMATCH; + op->value = number_expr(fields); + } + + else if (optype == RLIST) { + taddr list = parse_reglist(&p); + + if (list >= 0) { + op->value = number_expr(list); + if (*p == '^') { + p++; + op->flags |= OFL_FORCE; /* set "load PSR / force user mode" flag */ + } + } + else + return PO_NOMATCH; + } + + else + ierror(0); + } + + return (skip(p)-start < len) ? PO_NOMATCH : PO_MATCH; +} + + +static void create_mapping_symbol(int type,section *sec,taddr pc) +/* create mapping symbol ($a, $t, $d) as required by ARM ELF ABI */ +{ + static char names[3][4] = { "$a","$t","$d" }; + static int types[3] = { TYPE_FUNCTION,TYPE_FUNCTION,TYPE_OBJECT }; + symbol *sym; + + if (typeTYPE_DATA) + ierror(0); + if (elfoutput) { + sym = mymalloc(sizeof(symbol)); + sym->type = LABSYM; + sym->flags = types[type]; + sym->name = names[type]; + sym->sec = sec; + sym->pc = pc; + sym->expr = 0; + sym->size = 0; + sym->align = 0; + add_symbol(sym); + } + last_data_type = type; +} + + +size_t eval_thumb_operands(instruction *ip,section *sec,taddr pc, + uint16_t *insn,dblock *db) +/* evaluate expressions and try to optimize THUMB instruction, + return size of instruction */ +{ + operand op; + mnemonic *mnemo = &mnemonics[ip->code]; + int opcnt = 0; + size_t isize = 2; + + if (insn) { + if (pc & 1) + cpu_error(27); /* instruction at unaligned address */ + + if (ip->op[0] == NULL) { + /* handle inst. without operands, which don't have Thumb entries */ + if (ip->code == OC_NOP) + *insn = 0x46c0; /* nop => mov r0,r0 */ + + return 2; + } + else + *insn = (uint16_t)mnemo->ext.opcode; + } + + for (opcnt=0; opcntop[opcnt]!=NULL; opcnt++) { + taddr val; + symbol *base = NULL; + int btype; + + op = *(ip->op[opcnt]); + if (!eval_expr(op.value,&val,sec,pc)) + btype = find_base(op.value,&base,sec,pc); + + /* do optimizations first */ + + if (op.type==TPCLW || THBRANCH(op.type)) { + /* PC-relative offsets (take prefetch into account: PC+4) */ + if ((base!=NULL && btype==BASE_OK && !is_pc_reloc(base,sec)) || + base==NULL) { + /* no relocation required, can be resolved immediately */ + if (op.type == TPCLW) { + /* bit 1 of PC is forced to 0 */ + val -= (pc&~2) + 4; + } + else + val -= pc + 4; + + if (op.type == TBR08) { + if (val<-0x100 || val>0xfe) { + /* optimize to: B .+4 ; B label */ + if (insn) { + *insn++ ^= 0x100; /* negate branch-condition */ + *insn = 0xe000; /* B unconditional to label */ + } + if (val < 0) + val -= 2; /* backward-branches are 2 bytes longer */ + isize += 2; + op.type = TBR11; + } + } + else if (op.type == TBRHL) { + /* BL always consists of two instructions */ + isize += 2; + } + else if (op.type == TPCLW) { + /* @@@ optimization makes any sense? */ + op.type = TUIMA; + base = NULL; /* no more checks */ + } + } + else if (btype == BASE_OK) { + /* symbol is in a different section or externally declared */ + if (op.type == TBRHL) { + val -= THB_PREFETCH; + if (db) { + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?5:0,11,0,0x7ff000); + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?16+5:16+0,11,0,0xffe); + } + isize += 2; /* we need two instructions for a 23-bit branch */ + } + else if (op.type == TPCLW) { + /* val -= THB_PREFETCH; @@@ only positive offsets allowed! */ + op.type = TUIMA; + if (db) + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?8:0,8,0,0x3fc); + base = NULL; /* no more checks */ + } + else if (insn) + cpu_error(22); /* operation not allowed on external symbols */ + } + else if (insn) + cpu_error(22); /* operation not allowed on external symbols */ + } + + /* optimizations should be finished at this stage - + inserts operands into the opcode now: */ + + if (insn) { + + if (THREGOPER(op.type)) { + /* insert register operand, check was already done in parse_operand */ + if (!THPCORSP(op.type)) { + switch (op.type) { + case TRG02: + case THR02: + *insn |= val&7; + break; + case TRG05: + case THR05: + case TR5IN: + *insn |= (val&7) << 3; + break; + case TRG08: + case TR8IN: + *insn |= (val&7) << 6; + break; + case TRG10: + case TR10W: + *insn |= (val&7) << 8; + break; + default: + ierror(0); + break; + } + } + } + + else if (THREGLIST(op.type)) { + /* register list was already checked in parse_operand - just insert */ + *insn |= val; + } + + else if (THIMMOPER(op.type) || op.type==TSWI8) { + /* immediate operand */ + switch (op.type) { + case TUIM3: + if (val>=0 && val<=7) { + *insn |= val<<6; + } + else + cpu_error(25,3,(long)val); /* immediate offset out of range */ + break; + case TUIM5: + case TUI5I: + if (val>=0 && val<=0x1f) { + *insn |= val<<6; + } + else + cpu_error(25,5,(long)val); /* immediate offset out of range */ + break; + case TUI6I: + if (val>=0 && val<=0x3e) { + if ((val & 1) == 0) + *insn |= (val&0x3e)<<5; + else + cpu_error(26,2); /* offset has to be a multiple of 2 */ + } + else + cpu_error(25,6,(long)val); /* immediate offset out of range */ + break; + case TUI7I: + if (val>=0 && val<=0x7c) { + if ((val & 3) == 0) + *insn |= (val&0x7c)<<4; + else + cpu_error(26,4); /* offset has to be a multiple of 4 */ + } + else + cpu_error(25,7,(long)val); /* immediate offset out of range */ + break; + case TUIM8: + case TSWI8: + if (val>=0 && val<=0xff) { + *insn |= val; + } + else + cpu_error(25,8,(long)val); /* immediate offset out of range */ + break; + case TUIM9: + if (val>=0 && val<=0x1fc) { + if ((val & 3) == 0) + *insn |= val>>2; + else + cpu_error(26,4); /* offset has to be a multiple of 4 */ + } + else + cpu_error(25,9,(long)val); /* immediate offset out of range */ + break; + case TUIMA: + case TUIAI: + if (val>=0 && val<=0x3fc) { + if ((val & 3) == 0) + *insn |= val>>2; + else + cpu_error(26,4); /* offset has to be a multiple of 4 */ + } + else + cpu_error(25,10,(long)val); /* immediate offset out of range */ + break; + } + + if (base!=NULL && db!=NULL) { + if (btype == BASE_OK) { + if (op.type==TUIM5 || op.type==TUI5I) + add_extnreloc_masked(&db->relocs,base,val,REL_ABS, + arm_be_mode?5:6,5,0,0x1f); + else if (op.type == TSWI8) + add_extnreloc_masked(&db->relocs,base,val,REL_ABS, + arm_be_mode?8:0,8,0,0xff); + else + cpu_error(6); /* constant integer expression required */ + } + else + general_error(38); /* illegal relocation */ + } + } + + else if (op.type == TBR08) { + /* only write offset, relocs and optimizations are handled above */ + if (val & 1) + cpu_error(8,(long)val); /* branch to unaligned address */ + *insn |= (val>>1) & 0xff; + } + + else if (op.type == TBR11) { + /* only write offset, relocs and optimizations are handled above */ + if (val<-0x800 || val>0x7fe) + cpu_error(3,(long)val); /* branch offset is out of range */ + if (val & 1) + cpu_error(8,(long)val); /* branch to unaligned address */ + *insn |= (val>>1) & 0x7ff; + } + + else if (op.type == TBRHL) { + /* split 23-bit offset over two instructions, ignoring bit 0 */ + if (val<-0x400000 || val>0x3ffffe) + cpu_error(3,(long)val); /* branch offset is out of range */ + if (val & 1) + cpu_error(8,(long)val); /* branch to unaligned address */ + *insn++ |= (val>>12) & 0x7ff; + *insn = 0xf800 | ((val>>1) & 0x7ff); + } + + else + ierror(0); + } + } + + return isize; +} + + +#define ROTFAIL (0xffffff) + +static uint32_t rotated_immediate(uint32_t val) +/* check if a 32-bit value can be represented as 8-bit-rotated, + return ROTFAIL when impossible */ +{ + uint32_t i,a; + + for (i=0; i<32; i+=2) { + if ((a = val<>(32-i)) <= 0xff) + return (i<<7) | a; + } + return ROTFAIL; +} + + +static int negated_rot_immediate(uint32_t val,mnemonic *mnemo, + uint32_t *insn) +/* check if negating the ALU-operation makes a valid 8-bit-rotated value, + insert it into the current instruction, when successful */ +{ + uint32_t neg = rotated_immediate(-val); + uint32_t inv = rotated_immediate(~val); + uint32_t op = (mnemo->ext.opcode & 0x01e00000) >> 21; + + switch (op) { + /* AND <-> BIC */ + case 0: op=14; val=inv; break; + case 14: op=0; val=inv; break; + /* ADD <-> SUB */ + case 2: op=4; val=neg; break; + case 4: op=2; val=neg; break; + /* ADC <-> SBC */ + case 5: op=6; val=inv; break; + case 6: op=5; val=inv; break; + /* CMP <-> CMN */ + case 10: op=11; val=neg; break; + case 11: op=10; val=neg; break; + /* MOV <-> MVN */ + case 13: op=15; val=inv; break; + case 15: op=13; val=inv; break; + + default: return 0; + } + + if (val == ROTFAIL) + return 0; + + if (insn) { + *insn &= ~0x01e00000; + *insn |= (op<<21) | val; + } + return 1; +} + + +static uint32_t double_rot_immediate(uint32_t val,uint32_t *hi) +/* check if a 32-bit value can be represented by combining two + 8-bit rotated values, return ROTFAIL otherwise */ +{ + uint32_t i,a; + + for (i=0; i<32; i+=2) { + if (((a = val<>(32-i)) & 0xff) != 0) { + if (a & 0xff00) { + if (a & 0xffff0000) + continue; + *hi = ((i+24)<<7) | (a>>8); + } + else if (a & 0xff0000) { + if (a & 0xff000000) + continue; + *hi = ((i+16)<<7) | (a>>16); + } + else if (a & 0xff000000) + *hi = ((i+8)<<7) | (a>>24); + else + ierror(0); + + return (i<<7) | (a&0xff); + } + } + + return ROTFAIL; +} + + +static uint32_t calc_2nd_rot_opcode(uint32_t op) +/* calculates ALU operation for second instruction */ +{ + if (op == 13) + op = 12; /* MOV + ORR */ + else if (op == 15) + op = 1; /* MVN + EOR */ + /* ADD and SUB stay the same */ + + return op << 21; +} + + +static int negated_double_rot_immediate(uint32_t val,uint32_t *insn) +/* check if negating the ALU-operation and/or a second ADD/SUB operation + makes a valid 8-bit-rotated value, insert it into the current + instruction, when successful */ +{ + uint32_t op = (*insn & 0x01e00000) >> 21; + + if ((op==2 || op==4 || op==13 || op==15) && insn!=NULL) { + /* combined instructions only possible for ADD/SUB/MOV/MVN */ + uint32_t lo,hi; + + *(insn+1) = *insn & ~0x01ef0000; + *(insn+1) |= (*insn&0xf000) << 4; /* Rn = Rd of first instruction */ + + if ((lo = double_rot_immediate(val,&hi)) != ROTFAIL) { + *insn++ |= hi; + *insn |= calc_2nd_rot_opcode(op) | lo; + return 1; + } + + /* @@@ try negated or inverted values */ + } + + return 0; +} + + +static uint32_t get_condcode(instruction *ip) +/* returns condition (bit 31-28) from instruction's qualifiers */ +{ + const char *cc = condition_codes; + char *q; + + if (q = ip->qualifiers[0]) { + uint32_t code = 0; + + while (*cc) { + if (!strnicmp(q,cc,2) && *(q+2)=='\0') + break; + cc += 2; + code++; + } + if (*cc) { /* condition code in qualifier valid */ + if (code == 16) /* hs -> cs */ + code = 2; + else if (code==17 || code==18) /* lo/ul -> cc */ + code = 3; + + return code<<28; + } + } + + return 0xe0000000; /* AL - always */ +} + + +static int get_addrmode(instruction *ip) +/* return addressing mode from instruction's qualifiers */ +{ + char *q; + + if ((q = ip->qualifiers[1]) == NULL) + q = ip->qualifiers[0]; + + if (q) { + const char **am = addrmode_strings; + int mode = AM_DA; + + do { + if (!stricmp(*am,q)) + break; + am++; + mode++; + } + while (*am); + + if (*am != NULL) + return mode; + } + + return AM_NONE; +} + + +size_t eval_arm_operands(instruction *ip,section *sec,taddr pc, + uint32_t *insn,dblock *db) +/* evaluate expressions and try to optimize ARM instruction, + return size of instruction */ +{ + operand op; + mnemonic *mnemo = &mnemonics[ip->code]; + int am = get_addrmode(ip); + int aa4ldst = 0; + int opcnt = 0; + size_t isize = 4; + taddr chkreg = -1; + + if (insn) { + if (pc & 3) + cpu_error(27); /* instruction at unaligned address */ + + *insn = mnemo->ext.opcode | get_condcode(ip); + + if ((mnemo->ext.flags & SETCC)!=0 && am==AM_S) + *insn |= 0x00100000; /* set-condition-codes flag */ + + if ((mnemo->ext.flags & SETPSR)!=0 && am==AM_P) { + /* Rd = R15 for changing the PSR. Recommended for ARM2/250/3 only. */ + *insn |= 0x0000f000; + if (cpu_type & ~AA2) + cpu_error(28); /* deprecated on 32-bit architectures */ + } + + if (!strcmp(mnemo->name,"ldr") || !strcmp(mnemo->name,"str")) { + if (am==AM_T || am==AM_B || am==AM_BT || am==AM_TB) { /* std. ldr/str */ + if (am != AM_B) { + *insn |= 0x00200000; /* W-flag for post-indexed mode */ + *insn &= ~0x01000000; /* force post-indexed */ + } + if (am != AM_T) + *insn |= 0x00400000; /* B-flag for byte-transfer */ + } + else if (am==AM_SB || am==AM_H || am==AM_SH) { /* arch.4 ldr/str */ + if (cpu_type & AA4UP) { + /* take P-, I- and L-bit from previous standard instruction */ + *insn = (*insn&0xf1100000) + | (((*insn&0x02000000)^0x02000000)>>3) /* I-bit is flipped */ + | 0x90; + if (am != AM_H) { + if (*insn & 0x00100000) /* load */ + *insn |= 0x40; /* signed transfer */ + else + cpu_error(18,addrmode_strings[am]); /* illegal addr. mode */ + } + if (am != AM_SB) + *insn |= 0x20; /* halfword-transfer */ + aa4ldst = 1; + } + else + cpu_error(0); /* instruction not supported on selected arch. */ + } + else if (am != AM_NONE) + cpu_error(18,addrmode_strings[am]); /* illegal addr. mode */ + } + else if (ip->code == OC_SWP) { + if (am == AM_B) + *insn |= 0x00400000; /* swap bytes */ + else if (am != AM_NONE) + cpu_error(18,addrmode_strings[am]); /* illegal addr. mode */ + } + } + else { /* called by instruction_size() */ + if (am==AM_SB || am==AM_H || am==AM_SH) + aa4ldst = 1; + } + + for (opcnt=0; opcntop[opcnt]!=NULL; opcnt++) { + taddr val; + symbol *base = NULL; + int btype; + + op = *(ip->op[opcnt]); + if (!eval_expr(op.value,&val,sec,pc)) + btype = find_base(op.value,&base,sec,pc); + + /* do optimizations first */ + + if (op.type==PCL12 || op.type==PCLRT || + op.type==PCLCP || op.type==BRA24) { + /* PC-relative offsets (take prefetch into account: PC+8) */ + if ((base!=NULL && btype==BASE_OK && !is_pc_reloc(base,sec)) || + base==NULL) { + /* no relocation required, can be resolved immediately */ + val -= pc + 8; + + switch (op.type) { + case BRA24: + if (val>=0x2000000 || val<-0x2000000) { + /* @@@ optimize? to what? */ + if (insn) + cpu_error(3,(long)val); /* branch offset is out of range */ + } + break; + + case PCL12: + if ((!aa4ldst && val<0x1000 && val>-0x1000) || + (aa4ldst && val<0x100 && val>-0x100)) { + op.type = IMUD2; /* handle as normal #+/-Imm12 */ + if (val < 0) + val = -val; + else + op.flags |= OFL_UP; + base = NULL; /* no more checks */ + } + else { + if (opt_ldrpc && + ((!aa4ldst && val<0x100000 && val>-0x100000) || + (aa4ldst && val<0x10000 && val>-0x10000))) { + /* ADD/SUB Rd,PC,#offset&0xff000 */ + /* LDR/STR Rd,[Rd,#offset&0xfff] */ + if (insn) { + taddr v; + + *(insn+1) = *insn; + *insn &= 0xf0000000; /* clear all except cond. */ + if (val < 0) { + v = -val; + *insn |= 0x024f0a00; /* SUB */ + *(insn+1) &= ~0x00800000; /* clear U-bit */ + } + else { + v = val; + *insn |= 0x028f0a00; /* ADD */ + *(insn+1) |= 0x00800000; /* set U-bit */ + } + if (aa4ldst) + *insn |= (*(insn+1)&0xf000) | ((v&0xff00)>>8); + else + *insn |= (*(insn+1)&0xf000) | ((v&0xff000)>>12); + *(insn+1) &= ~0x000f0000; /* replace PC by Rd */ + *(insn+1) |= (*insn & 0xf000) << 4; + insn++; + } + if (val < 0) + val = -val; + else + op.flags |= OFL_UP; + val = aa4ldst ? (val & 0xff) : (val & 0xfff); + isize += 4; + op.type = IMUD2; + base = NULL; /* no more checks */ + } + else { + op.type = NOOP; + if (insn) + cpu_error(4,val); /* PC-relative ldr/str out of range */ + } + } + break; + + case PCLCP: + if (val<0x400 && val>-0x400) { + op.type = IMCP2; /* handle as normal #+/-Imm10>>2 */ + if (val < 0) + val = -val; + else + op.flags |= OFL_UP; + base = NULL; /* no more checks */ + } + else { + /* no optimization, because we don't have a free register */ + op.type = NOOP; + if (insn) + cpu_error(4,val); /* PC-relative ldc/stc out of range */ + } + break; + + case PCLRT: + op.type = NOOP; /* is handled here */ + if (val < 0) { + /* use SUB instead of ADD */ + if (insn) + *insn ^= 0x00c00000; + val = -val; + } + if ((val = rotated_immediate(val)) != ROTFAIL) { + if (insn) + *insn |= val; + } + else if (opt_adr || am==AM_L) { + /* ADRL or optimize ADR automatically to ADRL */ + uint32_t hi,lo; + + isize += 4; + if ((lo = double_rot_immediate(val,&hi)) != ROTFAIL) { + /* ADD/SUB Rd,PC,#hi8rotated */ + /* ADD/SUB Rd,Rd,#lo8rotated */ + if (insn) { + *(insn+1) = *insn & ~0xf0000; + *(insn+1) |= (*insn&0xf000) << 4; + *insn++ |= hi; + *insn |= lo; + } + } + else if (insn) + cpu_error(5,(uint32_t)val); /* Cannot make rot.immed.*/ + } + else if (insn) + cpu_error(5,(uint32_t)val); /* Cannot make rot.immed.*/ + break; + + default: + ierror(0); + } + } + else if (btype == BASE_OK) { + /* symbol is in a different section or externally declared */ + switch (op.type) { + case BRA24: + val -= ARM_PREFETCH; + if (db) + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?8:0,24,0,0x3fffffc); + break; + case PCL12: + op.type = IMUD2; + if (db) { + if (val<0x1000 && val>-0x1000) { + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?20:0,12,0,0x1fff); + base = NULL; /* don't add another REL_ABS below */ + } + else + cpu_error(22); /* operation not allowed on external symbols */ + } + break; + case PCLCP: + if (db) + cpu_error(22); /* operation not allowed on external symbols */ + break; + case PCLRT: + op.type = NOOP; + if (am==AM_L && val==0) { /* ADRL */ + isize += 4; /* always reserve two ADD instructions */ + if (insn!=NULL && db!=NULL) { + *(insn+1) = *insn & ~0xf0000; + *(insn+1) |= (*insn&0xf000) << 4; + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?24:0,8,0,0xff00); + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?32+24:32+0,8,0,0xff); + } + } + else if (val == 0) { /* ADR */ + if (db) + add_extnreloc_masked(&db->relocs,base,val,REL_PC, + arm_be_mode?24:0,8,0,0xff); + } + else if (db) + cpu_error(22); /* operation not allowed on external symbols */ + break; + default: + ierror(0); + } + } + else if (db) + cpu_error(22); /* operation not allowed on external symbols */ + } + + else if (op.type == IMROT) { + op.type = NOOP; /* is handled here */ + + if (base == NULL) { + uint32_t rotval; + + if ((rotval = rotated_immediate(val)) != ROTFAIL) { + if (insn) + *insn |= rotval; + } + else if (!negated_rot_immediate(val,mnemo,insn)) { + /* rotation, negation and inversion failed - try a 2nd operation */ + isize += 4; + if (insn) { + if (!negated_double_rot_immediate(val,insn)) + cpu_error(7,(uint32_t)val); /* const not suitable */ + } + } + } + else if (insn) + cpu_error(6); /* constant integer expression required */ + } + + /* optimizations should be finished at this stage - + inserts operands into the opcode now: */ + + if (insn) { + + if (REGOPER(op.type)) { + /* insert register operand */ + if (base!=NULL || val<0 || val>15) + cpu_error(9); /* not a valid ARM register */ + + if (REG19OPER(op.type)) + *insn |= val<<16; + else if (REG15OPER(op.type)) + *insn |= val<<12; + else if (REG11OPER(op.type)) + *insn |= val<<8; + else if (REG03OPER(op.type)) + *insn |= val; + + if (op.type==R3UD1 && !(*insn&0x01000000)) + cpu_error(21); /* post-indexed addressing mode expected */ + if (op.flags & OFL_WBACK) + *insn |= 0x00200000; + if (op.flags & OFL_UP) + *insn |= 0x00800000; + + /* some more checks: */ + if ((mnemo->ext.flags&NOPC) && val==15) + cpu_error(10); /* PC (r15) not allowed in this mode */ + if ((mnemo->ext.flags&NOPCR03) && val==15 && REG03OPER(op.type)) + cpu_error(11); /* PC (r15) not allowed for offset register Rm */ + if ((mnemo->ext.flags&NOPC) && val==15 && (op.flags&OFL_WBACK)) + cpu_error(12); /* PC (r15) not allowed with write-back */ + + /* check for illegal double register specifications */ + if (((mnemo->ext.flags&DIFR03) && REG03OPER(op.type)) || + ((mnemo->ext.flags&DIFR11) && REG11OPER(op.type)) || + ((mnemo->ext.flags&DIFR15) && REG15OPER(op.type)) || + ((mnemo->ext.flags&DIFR19) && REG19OPER(op.type))) { + if (chkreg != -1) { + if (val == chkreg) + cpu_error(13,(long)val); /* register was used multiple times */ + } + else + chkreg = val; + } + } + + else if (op.type == BRA24) { + /* only write offset, relocs and optimizations are handled above */ + if (val & 3) + cpu_error(8,(long)val); /* branch to unaligned address */ + *insn |= (val>>2) & 0xffffff; + } + + else if (op.type==IMUD1 || op.type==IMUD2) { + if (aa4ldst) { + /* insert splitted 8-bit immediate for signed/halfword ldr/str */ + if (val>=0 && val<=0xff) { + *insn |= ((val&0xf0)<<4) | (val&0x0f); + } + else + cpu_error(20,8,(long)val); /* immediate offset out of range */ + } + else { + /* insert immediate 12-bit with up/down flag */ + if (val>=0 && val<=0xfff) { + *insn |= val; + } + else + cpu_error(20,12,(long)val); /* immediate offset out of range */ + } + + if (op.type==IMUD1 && !(*insn&0x01000000)) + cpu_error(21); /* post-indexed addressing mode exptected */ + if (op.flags & OFL_WBACK) + *insn |= 0x00200000; /* set write-back flag */ + if (op.flags & OFL_UP) + *insn |= 0x00800000; /* set UP-flag */ + + if (base) { + if (btype == BASE_OK) { + if (EXTREF(base)) { + if (!aa4ldst) { + /* @@@ does this make any sense? */ + *insn |= 0x00800000; /* only UP */ + add_extnreloc_masked(&db->relocs,base,val,REL_ABS, + arm_be_mode?20:0,12,0,0xfff); + } + else + cpu_error(22); /* operation not allowed on external symbols */ + } + else + cpu_error(6); /* constant integer expression required */ + } + else + general_error(38); /* illegal relocation */ + } + } + + else if (op.type==IMCP1 || op.type==IMCP2) { + /* insert immediate 10-bit shifted left by 2, with up/down flag */ + if (val>=0 && val<=0x3ff) { + if ((val & 3) == 0) + *insn |= val>>2; + else + cpu_error(23); /* ldc/stc offset has to be a multiple of 4 */ + } + else + cpu_error(20,10,(long)val); /* immediate offset out of range */ + + if (op.flags & OFL_WBACK) + *insn |= 0x00200000; /* set write-back flag */ + if (op.flags & OFL_UP) + *insn |= 0x00800000; /* set UP-flag */ + + if (base) + cpu_error(6); /* constant integer expression required */ + } + + else if (op.type == SWI24) { + /* insert 24-bit immediate (SWI instruction) */ + if (val>=0 && val<0x1000000) { + *insn |= val; + if (base!=NULL && db!=NULL) + add_extnreloc_masked(&db->relocs,base,val,REL_ABS, + arm_be_mode?8:0,24,0,0xffffff); + } + else + cpu_error(16); /* 24-bit unsigned immediate expected */ + if (base) + cpu_error(6); /* constant integer expression required */ + } + + else if (op.type == IROTV) { + /* insert 4-bit rotate constant (even value, shifted right) */ + if (val>=0 && val<=30 && (val&1)==0) + *insn |= val << 7; + else + cpu_error(29,(long)val); /* must be even number between 0 and 30 */ + if (base) + cpu_error(6); /* constant integer expression required */ + } + + else if (op.type == IMMD8) { + /* unsigned 8-bit immediate constant, used together with IROTV */ + if (val>=0 && val<0x100 && base==NULL) + *insn |= val; + else + cpu_error(30,8,(long)val); /* 8-bit unsigned constant required */ + } + + else if (SHIFTOPER(op.type)) { + /* insert a register- or immediate shift */ + int sh_op = op.flags & OFL_SHIFTOP; + + if (aa4ldst) + cpu_error(19); /* signed/halfword ldr/str doesn't support shifts */ + if (op.type==SHIM1 && !(*insn&0x01000000)) + cpu_error(21); /* post-indexed addressing mode exptected */ + + if (op.flags & OFL_IMMEDSHIFT) { + if (sh_op==1 || sh_op==2) { /* lsr/asr permit shift-count #32 */ + if (val == 32) + val = 0; + } + if (base==NULL && val>=0 && val<32) { + *insn |= (val<<7) | ((op.flags&OFL_SHIFTOP)<<5); + if (op.flags & OFL_WBACK) + *insn |= 0x00200000; + } + else + cpu_error(14,(long)val); /* illegal immediate shift count */ + } + else { /* shift count in register */ + if (base==NULL && val>=0 && val<16) { + *insn |= (val<<8) | ((op.flags&OFL_SHIFTOP)<<5) | 0x10; + } + else + cpu_error(15); /* not a valid shift register */ + } + } + + else if (CPOPCODE(op.type)) { + /* insert coprocessor operation/type */ + if (base == NULL) { + switch (op.type) { + case CPOP3: + if (val>=0 && val<8) + *insn |= val<<21; + else + cpu_error(24,val); /* illegal coprocessor operation */ + break; + case CPOP4: + if (val>=0 && val<16) + *insn |= val<<20; + else + cpu_error(24,val); /* illegal coprocessor operation */ + break; + case CPTYP: + if (val>=0 && val<8) + *insn |= val<<5; + else + cpu_error(24,val); /* illegal coprocessor operation */ + break; + default: ierror(0); + } + } + else + cpu_error(24,val); /* illegal coprocessor operation */ + } + + else if (op.type==CSPSR || op.type==PSR_F) { + /* insert PSR type - no checks needed */ + *insn |= val<<16; + if (op.flags & OFL_SPSR) + *insn |= 0x00400000; + } + + else if (op.type == RLIST) { + /* insert register-list field */ + if (amAM_ED) + cpu_error(18,addrmode_strings[am]); /* illegal addr. mode */ + if (am>=AM_FA && am<=AM_ED) { + /* fix stack-addressing mode */ + if (!(mnemo->ext.opcode & 0x00100000)) + am ^= 3; /* invert P/U modes for store operations */ + } + *insn |= ((am&3)<<23) | val; + if (op.flags & OFL_FORCE) + *insn |= 0x00400000; + } + + else if (op.type != NOOP) + ierror(0); + } + } + + return isize; +} + + +size_t instruction_size(instruction *ip,section *sec,taddr pc) +/* Calculate the size of the current instruction; must be identical + to the data created by eval_instruction. */ +{ + if (mnemonics[ip->code].ext.flags & THUMB) + return eval_thumb_operands(ip,sec,pc,NULL,NULL); + + /* ARM mode */ + return eval_arm_operands(ip,sec,pc,NULL,NULL); +} + + +dblock *eval_instruction(instruction *ip,section *sec,taddr pc) +/* Convert an instruction into a DATA atom including relocations, + if necessary. */ +{ + dblock *db = new_dblock(); + int inst_type; + + if (sec != last_section) { + last_section = sec; + last_data_type = -1; + } + inst_type = (mnemonics[ip->code].ext.flags & THUMB) ? TYPE_THUMB : TYPE_ARM; + + if (inst_type == TYPE_THUMB) { + uint16_t insn[2]; + + if (db->size = eval_thumb_operands(ip,sec,pc,insn,db)) { + unsigned char *d = db->data = mymalloc(db->size); + int i; + + for (i=0; isize/2; i++) + d = setval(arm_be_mode,d,2,insn[i]); + } + } + + else { /* ARM mode */ + uint32_t insn[2]; + + if (db->size = eval_arm_operands(ip,sec,pc,insn,db)) { + unsigned char *d = db->data = mymalloc(db->size); + int i; + + for (i=0; isize/4; i++) + d = setval(arm_be_mode,d,4,insn[i]); + } + } + + if (inst_type != last_data_type) + create_mapping_symbol(inst_type,sec,pc); + + return db; +} + + +dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc) +/* Create a dblock (with relocs, if necessary) for size bits of data. */ +{ + dblock *db = new_dblock(); + taddr val; + + if (sec != last_section) { + last_section = sec; + last_data_type = -1; + } + + if ((bitsize & 7) || bitsize > 64) + cpu_error(17,bitsize); /* data size not supported */ + + if (op->type!=DATA_OP && op->type!=DATA64_OP) + ierror(0); + + db->size = bitsize >> 3; + db->data = mymalloc(db->size); + + if (op->type == DATA64_OP) { + thuge hval; + + if (!eval_expr_huge(op->value,&hval)) + general_error(59); /* cannot evaluate huge integer */ + huge_to_mem(arm_be_mode,db->data,db->size,hval); + } + else { + if (!eval_expr(op->value,&val,sec,pc)) { + symbol *base; + int btype; + + btype = find_base(op->value,&base,sec,pc); + if (base) + add_extnreloc(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS,0,bitsize,0); + else if (btype != BASE_NONE) + general_error(38); /* illegal relocation */ + } + switch (db->size) { + case 1: + db->data[0] = val & 0xff; + break; + case 2: + case 4: + setval(arm_be_mode,db->data,db->size,val); + break; + default: + ierror(0); + break; + } + } + + if (last_data_type != TYPE_DATA) + create_mapping_symbol(TYPE_DATA,sec,pc); + + return db; +} + + +int init_cpu() +{ + char r[4]; + int i; + + for (i=0; i 1) + inst_alignment = thumb_mode ? 2 : 4; + return 1; +} + + +int cpu_args(char *p) +{ + if (!strncmp(p,"-m",2)) { + p += 2; + if (!strcmp(p,"2")) cpu_type = ARM2; + else if (!strcmp(p,"250")) cpu_type = ARM250; + else if (!strcmp(p,"3")) cpu_type = ARM3; + else if (!strcmp(p,"6")) cpu_type = ARM6; + else if (!strcmp(p,"600")) cpu_type = ARM600; + else if (!strcmp(p,"610")) cpu_type = ARM610; + else if (!strcmp(p,"7")) cpu_type = ARM7; + else if (!strcmp(p,"710")) cpu_type = ARM710; + else if (!strcmp(p,"7500")) cpu_type = ARM7500; + else if (!strcmp(p,"7d")) cpu_type = ARM7d; + else if (!strcmp(p,"7di")) cpu_type = ARM7di; + else if (!strcmp(p,"7dm")) cpu_type = ARM7dm; + else if (!strcmp(p,"7dmi")) cpu_type = ARM7dmi; + else if (!strcmp(p,"7tdmi")) cpu_type = ARM7tdmi; + else if (!strcmp(p,"8")) cpu_type = ARM8; + else if (!strcmp(p,"810")) cpu_type = ARM810; + else if (!strcmp(p,"9")) cpu_type = ARM9; + else if (!strcmp(p,"920")) cpu_type = ARM920; + else if (!strcmp(p,"920t")) cpu_type = ARM920t; + else if (!strcmp(p,"9tdmi")) cpu_type = ARM9tdmi; + else if (!strcmp(p,"sa1")) cpu_type = SA1; + else if (!strcmp(p,"strongarm")) cpu_type = STRONGARM; + else if (!strcmp(p,"strongarm110")) cpu_type = STRONGARM110; + else if (!strcmp(p,"strongarm1100")) cpu_type = STRONGARM1100; + else return 0; + } + else if (!strncmp(p,"-a",2)) { + p += 2; + if (!strcmp(p,"2")) cpu_type = AA2; + else if (!strcmp(p,"3")) cpu_type = AA3; + else if (!strcmp(p,"3m")) cpu_type = AA3M; + else if (!strcmp(p,"4")) cpu_type = AA4; + else if (!strcmp(p,"4t")) cpu_type = AA4T; + else return 0; + } + else if (!strcmp(p,"-little")) + arm_be_mode = 0; + else if (!strcmp(p,"-big")) + arm_be_mode = 1; + else if (!strcmp(p,"-thumb")) + thumb_mode = 1; + else if (!strcmp(p,"-opt-ldrpc")) + opt_ldrpc = 1; + else if (!strcmp(p,"-opt-adr")) + opt_adr = 1; + + return 1; +} diff --git a/vasm-1/cpus/arm/cpu.h b/vasm-1/cpus/arm/cpu.h new file mode 100644 index 0000000..0c0bbd7 --- /dev/null +++ b/vasm-1/cpus/arm/cpu.h @@ -0,0 +1,214 @@ +/* cpu.h ARM cpu-description header-file */ +/* (c) in 2004,2014,2016 by Frank Wille */ + +#define LITTLEENDIAN (!arm_be_mode) +#define BIGENDIAN (arm_be_mode) +#define VASM_CPU_ARM 1 + +/* maximum number of operands in one mnemonic */ +#define MAX_OPERANDS 6 + +/* maximum number of mnemonic-qualifiers per mnemonic */ +#define MAX_QUALIFIERS 2 +/* but no qualifiers for macros */ +#define NO_MACRO_QUALIFIERS + +/* valid parentheses for cpu's operands */ +#define START_PARENTH(x) ((x)=='(' || (x)=='{') +#define END_PARENTH(x) ((x)==')' || (x)=='}') + +/* data type to represent a target-address */ +typedef int32_t taddr; +typedef uint32_t utaddr; + +/* minimum instruction alignment */ +#define INST_ALIGN 0 /* Handled internally! */ + +/* default alignment for n-bit data */ +#define DATA_ALIGN(n) ((n)<=8 ? 1 : ((n)<=16 ? 2 : 4)) + +/* operand class for n-bit data definitions */ +#define DATA_OPERAND(n) (n==64 ? DATA64_OP : DATA_OP) + +/* returns true when instruction is valid for selected cpu */ +#define MNEMONIC_VALID(i) cpu_available(i) + + +/* type to store each operand */ +typedef struct { + uint16_t type; /* type of operand from mnemonic.operand_type */ + uint16_t flags; /* see below */ + expr *value; /* single register, immed. val. or branch loc.*/ +} operand; + +/* flags: */ +#define OFL_SHIFTOP (0x0003) /* mask for shift-operation */ +#define OFL_IMMEDSHIFT (0x0004) /* uses immediate shift value */ +#define OFL_WBACK (0x0008) /* set write-back flag in opcode */ +#define OFL_UP (0x0010) /* set up-flag, add offset to base */ +#define OFL_SPSR (0x0020) /* 1:SPSR, 0:CPSR */ +#define OFL_FORCE (0x0040) /* LDM/STM PSR & force user bit */ + + +/* operand types - WARNING: the order is important! See defines below. */ +enum { + /* ARM operands */ + NOOP=0, + DATA_OP, /* data operand */ + DATA64_OP, /* 64-bit data operand (greater than taddr) */ + BRA24, /* 24-bit branch offset to label */ + PCL12, /* 12-bit PC-relative offset with up/down-flag to label */ + PCLCP, /* 8-bit * 4 PC-relative offset with up/down-flag to label */ + PCLRT, /* 8-bit rotated PC-relative offset to label */ + CPOP4, /* 4-bit coprocessor operation code at 23..20 */ + CPOP3, /* 3-bit coprocessor operation code at 23..21 */ + CPTYP, /* 3-bit coprocessor operation type at 7..5 */ + SWI24, /* 24-bit immediate at 23..0 (SWI instruction) */ + IROTV, /* explicit 4-bit rotate value at 11..8 */ + REG03, /* Rn at 3..0 */ + REG11, /* Rn at 11..8 */ + REG15, /* Rn at 15..12 */ + REG19, /* Rn at 19..16 */ + R19WB, /* Rn at 19..16 with optional write-back '!' */ + R19PR, /* [Rn, pre-indexed at 19..16 */ + R19PO, /* [Rn], post-indexed or indir. without index, at 19..16 */ + R3UD1, /* +/-Rn], pre-indexed at 3..0 with optional write-back '!' */ + R3UD2, /* +/-Rn, at 3..0, pre- or post-indexed */ + IMUD1, /* #+/-Imm12] pre-indexed with ']' and optional w-back '!' */ + IMUD2, /* #+/-Imm12 post-indexed */ + IMCP1, /* #+/-Imm10>>2 pre-indexed with ']' and optional w-back '!' */ + IMCP2, /* #+/-Imm10>>2 post-indexed */ + IMMD8, /* #Immediate, 8-bit */ + IMROT, /* #Imm32, 8-bit auto-rotated */ + SHIFT, /* Rs | #Imm5 | RRX = ROR #0 */ + SHIM1, /* #Imm5 | RRX, pre-indexed with terminating ] or ]! */ + SHIM2, /* #Imm5 | RRX, post-indexed */ + CSPSR, /* CPSR or SPSR */ + PSR_F, /* PSR-field: SPSR_, CPSR_ */ + RLIST, /* register list */ + + /* THUMB operands */ + TRG02, /* Rn at 2..0 */ + TRG05, /* Rn at 5..3 */ + TRG08, /* Rn at 8..6 */ + TRG10, /* Rn at 10..8 */ + THR02, /* Hi-Rn at 2..0 */ + THR05, /* Hi-Rn at 5..3 */ + TR5IN, /* [Rn at 5..3 */ + TR8IN, /* Rn] at 8..6 */ + TR10W, /* Rn! at 10..8 with write-back '!' */ + TPCRG, /* "PC" */ + TSPRG, /* "SP" */ + TPCPR, /* "[PC" */ + TSPPR, /* "[SP" */ + TRLST, /* register list for r0-r7 */ + TRLLR, /* extended register list, includes LR */ + TRLPC, /* extended register list, includes PC */ + TUIM3, /* 3-bit unsigned immediate at 8..6 */ + TUIM5, /* 5-bit unsigned immediate at 10..6 */ + TUIM8, /* 8-bit unsigned immediate at 7..0 */ + TUIM9, /* 9-bit unsigned immediate >> 2 at 6..0 */ + TUIMA, /* 10-bit unsigned immediate >> 2 at 7..0 */ + TUI5I, /* 5-bit unsigned immediate at 10..6 with terminating ] */ + TUI6I, /* 6-bit unsigned immediate >> 1 at 10..6 with terminating ] */ + TUI7I, /* 7-bit unsigned immediate >> 2 at 10..6 with terminating ] */ + TUIAI, /* 10-bit unsigned immediate >> 2 at 7..0 with terminating ] */ + TSWI8, /* 8-bit immediate at 7..0 (SWI instruction) */ + TPCLW, /* PC-relative label, has to fit into 10-bit uns.imm. >> 2 */ + TBR08, /* 9-bit branch offset >> 1 to label at 7..0 */ + TBR11, /* 12-bit branch offset >> 1 to label at 10..0 */ + TBRHL /* 23-bit branch offset >> 1 splitted into two 11-bit instr. */ +}; + +#define ARMOPER(x) ((x)>=BRA24 && (x)<=RLIST) +#define STDOPER(x) ((x)>=DATA_OP && (x)<=IMROT) +#define CPOPCODE(x) ((x)>=CPOP4 && (x)<=CPTYP) +#define REGOPER(x) ((x)>=REG03 && (x)<=R3UD2) +#define REG19OPER(x) ((x)>=REG19 && (x)<=R19PO) +#define REG15OPER(x) ((x)==REG15) +#define REG11OPER(x) ((x)==REG11) +#define REG03OPER(x) ((x)==REG03 || (x)==R3UD1 || (x)==R3UD2) +#define UPDOWNOPER(x) ((x)>=R3UD1 && (x)<=IMCP2) +#define IMMEDOPER(x) ((x)>=IMUD1 && (x)<=IMROT) +#define SHIFTOPER(x) ((x)>=SHIFT && (x)<=SHIM2) + +#define THUMBOPER(x) ((x)==0 || (x)>=TRG02) +#define THREGOPER(x) ((x)>=TRG02 && (x)<=TSPPR) +#define THPCORSP(x) ((x)>=TPCRG && (x)<=TSPPR) +#define THREGLIST(x) ((x)>=TRLST && (x)<=TRLPC) +#define THIMMOPER(x) ((x)>=TUIM3 && (x)<=TUIAI) +#define THIMMINDIR(x) ((x)>=TUI5I && (x)<=TUIAI) +#define THBRANCH(x) ((x)>=TBR08 && (x)<=TBRHL) + + +/* additional mnemonic data */ +typedef struct { + uint32_t opcode; + uint32_t available; + uint32_t flags; +} mnemonic_extension; + +/* flags: */ +#define DIFR19 (0x00000001) /* DIFFRxx registers must be different */ +#define DIFR15 (0x00000002) +#define DIFR11 (0x00000004) +#define DIFR03 (0x00000008) +#define NOPC (0x00000010) /* R15 is not allowed as source or dest. */ +#define NOPCR03 (0x00000020) /* R15 is not allowed for Rm (3..0) */ +#define NOPCWB (0x00000040) /* R15 is not allowed in Write-Back mode */ +#define SETCC (0x00000100) /* instruction supports S-bit */ +#define SETPSR (0x00000200) /* instruction supports P-bit */ +#define THUMB (0x10000000) /* THUMB instruction */ + + +/* register symbols */ +#define HAVE_REGSYMS +#define REGSYMHTSIZE 256 + + +/* cpu types for availability check */ +#define ARM2 (1L<<0) +#define ARM250 (1L<<1) +#define ARM3 (1L<<2) +#define ARM6 (1L<<3) +#define ARM60 (1L<<4) +#define ARM600 (1L<<5) +#define ARM610 (1L<<6) +#define ARM7 (1L<<7) +#define ARM710 (1L<<8) +#define ARM7500 (1L<<9) +#define ARM7d (1L<<10) +#define ARM7di (1L<<11) +#define ARM7dm (1L<<12) +#define ARM7dmi (1L<<13) +#define ARM7tdmi (1L<<14) +#define ARM8 (1L<<15) +#define ARM810 (1L<<16) +#define ARM9 (1L<<17) +#define ARM920 (1L<<18) +#define ARM920t (1L<<19) +#define ARM9tdmi (1L<<20) +#define SA1 (1L<<21) +#define STRONGARM (1L<<22) +#define STRONGARM110 (1L<<23) +#define STRONGARM1100 (1L<<24) + +/* ARM architectures */ +#define AA2 (ARM2|ARM250|ARM3) +#define AA3 (ARM6|ARM60|ARM600|ARM610|ARM7|ARM710|ARM7500|ARM7d|ARM7di) +#define AA3M (ARM7dm|ARM7dmi) +#define AA4 (ARM8|ARM810|ARM9|ARM920|SA1|STRONGARM|STRONGARM110|STRONGARM1100) +#define AA4T (ARM7tdmi|ARM920t|ARM9tdmi) + +#define AA4TUP (AA4T) +#define AA4UP (AA4|AA4T) +#define AA3MUP (AA3M|AA4|AA4T) +#define AA3UP (AA3|AA3M|AA4|AA4T) +#define AA2UP (AA2|AA3|AA3M|AA4|AA4T) +#define AAANY (~0) + + +/* exported by cpu.c */ +extern int arm_be_mode; + +int cpu_available(int); diff --git a/vasm-1/cpus/arm/cpu_errors.h b/vasm-1/cpus/arm/cpu_errors.h new file mode 100644 index 0000000..66f7f46 --- /dev/null +++ b/vasm-1/cpus/arm/cpu_errors.h @@ -0,0 +1,31 @@ + "instruction not supported on selected architecture",ERROR, + "trailing garbage in operand",WARNING, + "label from current section required",ERROR, + "branch offset (%ld) is out of range",ERROR, + "PC-relative load/store (offset %ld) out of range",ERROR, + "cannot make rotated immediate from PC-relative offset (0x%lx)",ERROR,/*05*/ + "constant integer expression required",ERROR, + "constant (0x%lx) not suitable for 8-bit rotated immediate",ERROR, + "branch to an unaligned address (offset %ld)",ERROR, + "not a valid ARM register",ERROR, + "PC (r15) not allowed in this mode",ERROR, /*10*/ + "PC (r15) not allowed for offset register Rm",ERROR, + "PC (r15) not allowed with write-back",ERROR, + "register r%ld was used multiple times",ERROR, + "illegal immediate shift count (%ld)",ERROR, + "not a valid shift register",ERROR, /*15*/ + "24-bit unsigned immediate expected",ERROR, + "data size %d not supported",ERROR, + "illegal addressing mode: %s",ERROR, + "signed/halfword ldr/str doesn't support shifts",ERROR, + "%d-bit immediate offset out of range (%ld)",ERROR, /*20*/ + "post-indexed addressing mode exptected",ERROR, + "operation not allowed on external symbols",ERROR, + "ldc/stc offset has to be a multiple of 4",ERROR, + "illegal coprocessor operation mode or type: %ld\n",ERROR, + "%d-bit unsigned immediate offset out of range (%ld)",ERROR, /*25*/ + "offset has to be a multiple of %d",ERROR, + "instruction at unaligned address",ERROR, + "TSTP/TEQP/CMNP/CMPP deprecated on 32-bit architectures",WARNING, + "rotate constant must be an even number between 0 and 30: %ld",ERROR, + "%d-bit unsigned constant required: %ld",ERROR, /*30*/ diff --git a/vasm-1/cpus/arm/opcodes.h b/vasm-1/cpus/arm/opcodes.h new file mode 100644 index 0000000..3302fb2 --- /dev/null +++ b/vasm-1/cpus/arm/opcodes.h @@ -0,0 +1,201 @@ + "add", {REG15,REG19,IMROT}, {0x02800000,AAANY,SETCC}, + "add", {REG15,REG19,IMMD8,IROTV}, {0x02800000,AAANY,SETCC}, + "add", {REG15,REG19,REG03}, {0x00800000,AAANY,SETCC}, + "add", {REG15,REG19,REG03,SHIFT}, {0x00800000,AAANY,SETCC}, + "add", {TRG02,TRG05,TRG08}, {0x1800,AA4TUP,THUMB}, + "add", {TRG02,TRG05,TUIM3}, {0x1c00,AA4TUP,THUMB}, + "add", {TRG10,TUIM8}, {0x3000,AA4TUP,THUMB}, + "add", {TRG02,THR05}, {0x4440,AA4TUP,THUMB}, + "add", {THR02,TRG05}, {0x4480,AA4TUP,THUMB}, + "add", {THR02,THR05}, {0x44c0,AA4TUP,THUMB}, + "add", {TRG10,TPCRG,TUIMA}, {0xa000,AA4TUP,THUMB}, + "add", {TRG10,TSPRG,TUIMA}, {0xa800,AA4TUP,THUMB}, + "add", {TSPRG,TUIM9}, {0xb000,AA4TUP,THUMB}, + "adc", {REG15,REG19,IMROT}, {0x02a00000,AAANY,SETCC}, + "adc", {REG15,REG19,IMMD8,IROTV}, {0x02a00000,AAANY,SETCC}, + "adc", {REG15,REG19,REG03}, {0x00a00000,AAANY,SETCC}, + "adc", {REG15,REG19,REG03,SHIFT}, {0x00a00000,AAANY,SETCC}, + "adc", {TRG02,TRG05}, {0x4140,AA4TUP,THUMB}, + "adr", {REG15,PCLRT}, {0x028f0000,AAANY,0}, + "adr", {TRG10,TPCLW}, {0xa000,AA4TUP,THUMB}, + "and", {REG15,REG19,IMROT}, {0x02000000,AAANY,SETCC}, + "and", {REG15,REG19,IMMD8,IROTV}, {0x02000000,AAANY,SETCC}, + "and", {REG15,REG19,REG03}, {0x00000000,AAANY,SETCC}, + "and", {REG15,REG19,REG03,SHIFT}, {0x00000000,AAANY,SETCC}, + "and", {TRG02,TRG05}, {0x4000,AA4TUP,THUMB}, + "asr", {TRG02,TRG05,TUIM5}, {0x1000,AA4TUP,THUMB}, + "asr", {TRG02,TRG05}, {0x4100,AA4TUP,THUMB}, + "b", {BRA24}, {0x0a000000,AAANY,0}, + "b", {TBR11}, {0xe000,AA4TUP,THUMB}, + "beq", {TBR08}, {0xd000,AA4TUP,THUMB}, + "bne", {TBR08}, {0xd100,AA4TUP,THUMB}, + "bcs", {TBR08}, {0xd200,AA4TUP,THUMB}, + "bcc", {TBR08}, {0xd300,AA4TUP,THUMB}, + "bmi", {TBR08}, {0xd400,AA4TUP,THUMB}, + "bpl", {TBR08}, {0xd500,AA4TUP,THUMB}, + "bvs", {TBR08}, {0xd600,AA4TUP,THUMB}, + "bvc", {TBR08}, {0xd700,AA4TUP,THUMB}, + "bhi", {TBR08}, {0xd800,AA4TUP,THUMB}, + "bls", {TBR08}, {0xd900,AA4TUP,THUMB}, + "bge", {TBR08}, {0xda00,AA4TUP,THUMB}, + "blt", {TBR08}, {0xdb00,AA4TUP,THUMB}, + "bgt", {TBR08}, {0xdc00,AA4TUP,THUMB}, + "ble", {TBR08}, {0xdd00,AA4TUP,THUMB}, + "bhs", {TBR08}, {0xd200,AA4TUP,THUMB}, + "blo", {TBR08}, {0xd300,AA4TUP,THUMB}, + "bul", {TBR08}, {0xd300,AA4TUP,THUMB}, + "bic", {REG15,REG19,IMROT}, {0x03c00000,AAANY,SETCC}, + "bic", {REG15,REG19,IMMD8,IROTV}, {0x03c00000,AAANY,SETCC}, + "bic", {REG15,REG19,REG03}, {0x01c00000,AAANY,SETCC}, + "bic", {REG15,REG19,REG03,SHIFT}, {0x01c00000,AAANY,SETCC}, + "bic", {TRG02,TRG05}, {0x4380,AA4TUP,THUMB}, + "bl", {BRA24}, {0x0b000000,AAANY,0}, + "bl", {TBRHL}, {0xf000,AA4TUP,THUMB}, + "bx", {REG03}, {0x012fff10,AA4TUP,NOPC}, + "bx", {TRG05}, {0x4700,AA4TUP,THUMB}, + "bx", {THR05}, {0x4740,AA4TUP,THUMB}, + "cdp", {REG11,CPOP4,REG15,REG19,REG03}, {0x0e000000,AA2UP,0}, + "cdp", {REG11,CPOP4,REG15,REG19,REG03,CPTYP},{0x0e000000,AA2UP,0}, + "cmn", {REG19,IMROT}, {0x03700000,AAANY,SETPSR}, + "cmn", {REG19,IMMD8,IROTV}, {0x03700000,AAANY,SETPSR}, + "cmn", {REG19,REG03}, {0x01700000,AAANY,SETPSR}, + "cmn", {REG19,REG03,SHIFT}, {0x01700000,AAANY,SETPSR}, + "cmn", {TRG02,TRG05}, {0x42c0,AA4TUP,THUMB}, + "cmp", {REG19,IMROT}, {0x03500000,AAANY,SETPSR}, + "cmp", {REG19,IMMD8,IROTV}, {0x03500000,AAANY,SETPSR}, + "cmp", {REG19,REG03}, {0x01500000,AAANY,SETPSR}, + "cmp", {REG19,REG03,SHIFT}, {0x01500000,AAANY,SETPSR}, + "cmp", {TRG10,TUIM8}, {0x2800,AA4TUP,THUMB}, + "cmp", {TRG02,TRG05}, {0x4280,AA4TUP,THUMB}, + "cmp", {TRG02,THR05}, {0x4540,AA4TUP,THUMB}, + "cmp", {THR02,TRG05}, {0x4580,AA4TUP,THUMB}, + "cmp", {THR02,THR05}, {0x45c0,AA4TUP,THUMB}, + "eor", {REG15,REG19,IMROT}, {0x02200000,AAANY,SETCC}, + "eor", {REG15,REG19,IMMD8,IROTV}, {0x02200000,AAANY,SETCC}, + "eor", {REG15,REG19,REG03}, {0x00200000,AAANY,SETCC}, + "eor", {REG15,REG19,REG03,SHIFT}, {0x00200000,AAANY,SETCC}, + "eor", {TRG02,TRG05}, {0x4040,AA4TUP,THUMB}, + "ldc", {REG11,REG15,PCLCP}, {0x0d1f0000,AA2UP,0}, + "ldc", {REG11,REG15,R19PR,IMCP1}, {0x0d100000,AA2UP,0}, + "ldc", {REG11,REG15,R19PO}, {0x0d100000,AA2UP,0}, + "ldc", {REG11,REG15,R19PO,IMCP2}, {0x0c100000,AA2UP,0}, + "ldm", {R19WB,RLIST}, {0x08100000,AAANY,NOPC}, + "ldmia",{TR10W,TRLST}, {0xc800,AA4TUP,THUMB}, + "ldr", {REG15,PCL12}, {0x051f0000,AAANY,NOPCWB}, + "ldr", {REG15,R19PR,IMUD1}, {0x05100000,AAANY,NOPCWB}, + "ldr", {REG15,R19PR,R3UD1}, {0x07100000,AAANY,NOPCWB|NOPCR03}, + "ldr", {REG15,R19PR,R3UD2,SHIM1}, {0x07100000,AAANY,NOPCWB|NOPCR03}, + "ldr", {REG15,R19PO}, {0x05900000,AAANY,NOPCWB}, + "ldr", {REG15,R19PO,IMUD2}, {0x04100000,AAANY,NOPCWB}, + "ldr", {REG15,R19PO,R3UD2}, {0x06100000,AAANY,NOPCWB|NOPCR03}, + "ldr", {REG15,R19PO,R3UD2,SHIM2}, {0x06100000,AAANY,NOPCWB|NOPCR03}, + "ldr", {TRG10,TPCLW}, {0x4800,AA4TUP,THUMB}, + "ldr", {TRG10,TPCPR,TUIAI}, {0x4800,AA4TUP,THUMB}, + "ldr", {TRG02,TR5IN,TR8IN}, {0x5800,AA4TUP,THUMB}, + "ldr", {TRG02,TR5IN,TUI7I}, {0x6800,AA4TUP,THUMB}, + "ldr", {TRG10,TSPPR,TUIAI}, {0x9800,AA4TUP,THUMB}, + "ldrb", {TRG02,TR5IN,TR8IN}, {0x5c00,AA4TUP,THUMB}, + "ldrb", {TRG02,TR5IN,TUI5I}, {0x7800,AA4TUP,THUMB}, + "ldrh", {TRG02,TR5IN,TR8IN}, {0x5a00,AA4TUP,THUMB}, + "ldrh", {TRG02,TR5IN,TUI6I}, {0x8800,AA4TUP,THUMB}, + "ldsb", {TRG02,TR5IN,TR8IN}, {0x5600,AA4TUP,THUMB}, + "ldsh", {TRG02,TR5IN,TR8IN}, {0x5e00,AA4TUP,THUMB}, + "lsl", {TRG02,TRG05,TUIM5}, {0x0000,AA4TUP,THUMB}, + "lsl", {TRG02,TRG05}, {0x4080,AA4TUP,THUMB}, + "lsr", {TRG02,TRG05,TUIM5}, {0x0800,AA4TUP,THUMB}, + "lsr", {TRG02,TRG05}, {0x40c0,AA4TUP,THUMB}, + "mcr", {REG11,CPOP3,REG15,REG19,REG03}, {0x0e000010,AA2UP,0}, + "mcr", {REG11,CPOP3,REG15,REG19,REG03,CPTYP},{0x0e000010,AA2UP,0}, + "mov", {REG15,IMROT}, {0x03a00000,AAANY,SETCC}, + "mov", {REG15,IMMD8,IROTV}, {0x03a00000,AAANY,SETCC}, + "mov", {REG15,REG03}, {0x01a00000,AAANY,SETCC}, + "mov", {REG15,REG03,SHIFT}, {0x01a00000,AAANY,SETCC}, + "mov", {TRG10,TUIM8}, {0x2000,AA4TUP,THUMB}, + "mov", {TRG02,TRG05}, {0x1c00,AA4TUP,THUMB}, + "mov", {TRG02,THR05}, {0x4640,AA4TUP,THUMB}, + "mov", {THR02,TRG05}, {0x4680,AA4TUP,THUMB}, + "mov", {THR02,THR05}, {0x46c0,AA4TUP,THUMB}, + "mrc", {REG11,CPOP3,REG15,REG19,REG03}, {0x0e100010,AA2UP,0}, + "mrc", {REG11,CPOP3,REG15,REG19,REG03,CPTYP},{0x0e100010,AA2UP,0}, + "mrs", {REG15,CSPSR}, {0x01000000,AA3UP,NOPC}, + "mla", {REG19,REG03,REG11,REG15}, {0x00200090,AA2UP,SETCC|NOPC|DIFR19|DIFR03}, + "msr", {PSR_F,IMROT}, {0x0320f000,AA3UP,0}, + "msr", {PSR_F,IMMD8,IROTV}, {0x0320f000,AA3UP,0}, + "msr", {PSR_F,REG03}, {0x0120f000,AA3UP,NOPC}, + "mul", {REG19,REG03,REG11}, {0x00000090,AA2UP,SETCC|NOPC|DIFR19|DIFR03}, + "mul", {TRG02,TRG05}, {0x4340,AA4TUP,THUMB}, + "mvn", {REG15,IMROT}, {0x03e00000,AAANY,SETCC}, + "mvn", {REG15,IMMD8,IROTV}, {0x03e00000,AAANY,SETCC}, + "mvn", {REG15,REG03}, {0x01e00000,AAANY,SETCC}, + "mvn", {REG15,REG03,SHIFT}, {0x01e00000,AAANY,SETCC}, + "mvn", {TRG02,TRG05}, {0x43c0,AA4TUP,THUMB}, + "neg", {TRG02,TRG05}, {0x4240,AA4TUP,THUMB}, + "nop", {0}, {0x01a00000,AAANY,0}, + "orr", {REG15,REG19,IMROT}, {0x03800000,AAANY,SETCC}, + "orr", {REG15,REG19,IMMD8,IROTV}, {0x03800000,AAANY,SETCC}, + "orr", {REG15,REG19,REG03}, {0x01800000,AAANY,SETCC}, + "orr", {REG15,REG19,REG03,SHIFT}, {0x01800000,AAANY,SETCC}, + "orr", {TRG02,TRG05}, {0x4300,AA4TUP,THUMB}, + "pop", {TRLPC}, {0xbc00,AA4TUP,THUMB}, + "push", {TRLLR}, {0xb400,AA4TUP,THUMB}, + "ror", {TRG02,TRG05}, {0x41c0,AA4TUP,THUMB}, + "rsb", {REG15,REG19,IMROT}, {0x02600000,AAANY,SETCC}, + "rsb", {REG15,REG19,IMMD8,IROTV}, {0x02600000,AAANY,SETCC}, + "rsb", {REG15,REG19,REG03}, {0x00600000,AAANY,SETCC}, + "rsb", {REG15,REG19,REG03,SHIFT}, {0x00600000,AAANY,SETCC}, + "rsc", {REG15,REG19,IMROT}, {0x02e00000,AAANY,SETCC}, + "rsc", {REG15,REG19,IMMD8,IROTV}, {0x02e00000,AAANY,SETCC}, + "rsc", {REG15,REG19,REG03}, {0x00e00000,AAANY,SETCC}, + "rsc", {REG15,REG19,REG03,SHIFT}, {0x00e00000,AAANY,SETCC}, + "smlal", {REG15,REG19,REG03,REG11}, {0x00e00090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03}, + "smull", {REG15,REG19,REG03,REG11}, {0x00c00090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03}, + "stc", {REG11,REG15,PCLCP}, {0x0d0f0000,AA2UP,0}, + "stc", {REG11,REG15,R19PR,IMCP1}, {0x0d000000,AA2UP,0}, + "stc", {REG11,REG15,R19PO}, {0x0d000000,AA2UP,0}, + "stc", {REG11,REG15,R19PO,IMCP2}, {0x0c000000,AA2UP,0}, + "stm", {R19WB,RLIST}, {0x08000000,AAANY,NOPC}, + "stmia",{TR10W,TRLST}, {0xc000,AA4TUP,THUMB}, + "str", {REG15,PCL12}, {0x050f0000,AAANY,NOPCWB}, + "str", {REG15,R19PR,IMUD1}, {0x05000000,AAANY,NOPCWB}, + "str", {REG15,R19PR,R3UD1}, {0x07000000,AAANY,NOPCWB|NOPCR03}, + "str", {REG15,R19PR,R3UD2,SHIM1}, {0x07000000,AAANY,NOPCWB|NOPCR03}, + "str", {REG15,R19PO}, {0x05800000,AAANY,NOPCWB}, + "str", {REG15,R19PO,IMUD2}, {0x04000000,AAANY,NOPCWB}, + "str", {REG15,R19PO,R3UD2}, {0x06000000,AAANY,NOPCWB|NOPCR03}, + "str", {REG15,R19PO,R3UD2,SHIM2}, {0x06000000,AAANY,NOPCWB|NOPCR03}, + "str", {TRG02,TR5IN,TR8IN}, {0x5000,AA4TUP,THUMB}, + "str", {TRG02,TR5IN,TUI7I}, {0x6000,AA4TUP,THUMB}, + "str", {TRG10,TSPPR,TUIAI}, {0x9000,AA4TUP,THUMB}, + "strb", {TRG02,TR5IN,TR8IN}, {0x5400,AA4TUP,THUMB}, + "strb", {TRG02,TR5IN,TUI5I}, {0x7000,AA4TUP,THUMB}, + "strh", {TRG02,TR5IN,TR8IN}, {0x5200,AA4TUP,THUMB}, + "strh", {TRG02,TR5IN,TUI6I}, {0x8000,AA4TUP,THUMB}, + "sbc", {REG15,REG19,IMROT}, {0x02c00000,AAANY,SETCC}, + "sbc", {REG15,REG19,IMMD8,IROTV}, {0x02c00000,AAANY,SETCC}, + "sbc", {REG15,REG19,REG03}, {0x00c00000,AAANY,SETCC}, + "sbc", {REG15,REG19,REG03,SHIFT}, {0x00c00000,AAANY,SETCC}, + "sbc", {TRG02,TRG05}, {0x4180,AA4TUP,THUMB}, + "sub", {REG15,REG19,IMROT}, {0x02400000,AAANY,SETCC}, + "sub", {REG15,REG19,IMMD8,IROTV}, {0x02400000,AAANY,SETCC}, + "sub", {REG15,REG19,REG03}, {0x00400000,AAANY,SETCC}, + "sub", {REG15,REG19,REG03,SHIFT}, {0x00400000,AAANY,SETCC}, + "sub", {TRG02,TRG05,TRG08}, {0x1a00,AA4TUP,THUMB}, + "sub", {TRG02,TRG05,TUIM3}, {0x1e00,AA4TUP,THUMB}, + "sub", {TRG10,TUIM8}, {0x3800,AA4TUP,THUMB}, + "sub", {TSPRG,TUIM9}, {0xb080,AA4TUP,THUMB}, + "svc", {SWI24}, {0x0f000000,AAANY,0}, + "svc", {TSWI8}, {0xdf00,AA4TUP,THUMB}, + "swi", {SWI24}, {0x0f000000,AAANY,0}, + "swi", {TSWI8}, {0xdf00,AA4TUP,THUMB}, + "swp", {REG15,REG03,R19PO}, {0x01000090,AA3UP,NOPC}, + "teq", {REG19,IMROT}, {0x03300000,AAANY,SETPSR}, + "teq", {REG19,IMMD8,IROTV}, {0x03300000,AAANY,SETPSR}, + "teq", {REG19,REG03}, {0x01300000,AAANY,SETPSR}, + "teq", {REG19,REG03,SHIFT}, {0x01300000,AAANY,SETPSR}, + "tst", {REG19,IMROT}, {0x03100000,AAANY,SETPSR}, + "tst", {REG19,IMMD8,IROTV}, {0x03100000,AAANY,SETPSR}, + "tst", {REG19,REG03}, {0x01100000,AAANY,SETPSR}, + "tst", {REG19,REG03,SHIFT}, {0x01100000,AAANY,SETPSR}, + "tst", {TRG02,TRG05}, {0x4200,AA4TUP,THUMB}, + "umlal", {REG15,REG19,REG03,REG11}, {0x00a00090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03}, + "umull", {REG15,REG19,REG03,REG11}, {0x00800090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03}, diff --git a/vasm-1/cpus/c16x/cpu.c b/vasm-1/cpus/c16x/cpu.c new file mode 100644 index 0000000..da65530 --- /dev/null +++ b/vasm-1/cpus/c16x/cpu.c @@ -0,0 +1,786 @@ +/* cpu.c example cpu-description file */ +/* (c) in 2002 by Volker Barthelmann */ + +#include "vasm.h" + +char *cpu_copyright="vasm c16x/st10 cpu backend 0.2c (c) in 2002-2005 Volker Barthelmann"; +char *cpuname="c16x"; + +mnemonic mnemonics[]={ +#include "opcodes.h" +}; + +int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]); + +int bitsperbyte=8; +int bytespertaddr=4; + +static int JMPA,JMPR,JMPS,JNB,JB,JBC,JNBS,JMP; +static int notrans,tojmpa; + +#define JMPCONV 256 +#define INVCC(c) (((c)&1)?(c)-1:(c)+1) + +#define ISBIT 1 + +typedef struct sfr { + struct sfr *next; + int flags; + unsigned int laddr,saddr,boffset; +} sfr; + + +sfr *first_sfr; +#define SFRHTSIZE 1024 +hashtable *sfrhash; + +static char *skip_reg(char *s,int *reg) +{ + int r=-1; + if(*s!='r'&&*s!='R'){ + cpu_error(1); + return s; + } + s++; + if(*s<'0'||*s>'9'){ + cpu_error(1); + return s; + } + r=*s++-'0'; + if(*s>='0'&&*s<='5') + r=10*r+*s++-'0'; + *reg=r; + return s; +} + +int parse_operand(char *p,int len,operand *op,int requires) +{ + op->type=-1; + op->mod=-1; + p=skip(p); + if(requires==OP_REL){ + char *s=p; + op->type=OP_REL; + op->offset=parse_expr(&s); + simplify_expr(op->offset); + if(s==p) + return 0; + else + return 1; + } + if(requires==OP_CC){ + op->type=OP_CC; + if(len<4||len>6||p[0]!='c'||p[1]!='c'||p[2]!='_') + return 0; + if(len==4){ + if(p[3]=='z') + op->cc=2; + else if(p[3]=='v') + op->cc=4; + else if(p[3]=='n') + op->cc=6; + else if(p[3]=='c') + op->cc=8; + else + return 0; + }else if(len==5){ + if(p[3]=='u'&&p[4]=='c') + op->cc=0; + else if(p[3]=='n'&&p[4]=='z') + op->cc=3; + else if(p[3]=='n'&&p[4]=='v') + op->cc=5; + else if(p[3]=='n'&&p[4]=='n') + op->cc=7; + else if(p[3]=='n'&&p[4]=='c') + op->cc=0; + else if(p[3]=='e'&&p[4]=='q') + op->cc=2; + else if(p[3]=='n'&&p[4]=='e') + op->cc=3; + else + return 0; + }else if(len==6){ + if(!strncmp(p+3,"ult",3)) + op->cc=8; + else if(!strncmp(p+3,"ule",3)) + op->cc=0xf; + else if(!strncmp(p+3,"uge",3)) + op->cc=0x9; + else if(!strncmp(p+3,"ugt",3)) + op->cc=0xe; + else if(!strncmp(p+3,"slt",3)) + op->cc=0xc; + else if(!strncmp(p+3,"sle",3)) + op->cc=0xb; + else if(!strncmp(p+3,"sge",3)) + op->cc=0xd; + else if(!strncmp(p+3,"sgt",3)) + op->cc=0xa; + else if(!strncmp(p+3,"net",3)) + op->cc=0x1; + else + return 0; + } + return 1; + } + if((p[0]=='r'||p[0]=='R')&&p[1]>='0'&&p[1]<='9'&&(len==2||p[2]=='.')){ + op->type=OP_GPR; + op->reg=p[1]-'0'; + op->regsfr=op->reg+0xf0; + if(len>2){ + op->type=OP_BADDR; + if(requires==OP_BADDR){ + p=skip(p+3); + op->boffset=parse_expr(&p); + op->offset=number_expr(op->regsfr); + } + } + }else if((p[0]=='r'||p[0]=='R')&&p[1]=='1'&&p[2]>='0'&&p[2]<='5'&&(len==3||p[3]=='.')){ + op->type=OP_GPR; + op->reg=(p[1]-'0')*10+p[2]-'0'; + op->regsfr=op->reg+0xf0; + if(len>3){ + op->type=OP_BADDR; + if(requires==OP_BADDR){ + p=skip(p+4); + op->boffset=parse_expr(&p); + op->offset=number_expr(op->regsfr); + } + } + }else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='l'||p[1]=='L')&&p[2]>='0'&&p[2]<='7'){ + op->type=OP_BGPR; + op->reg=(p[2]-'0')*2; + op->regsfr=op->reg+0xf0; + }else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='h'||p[1]=='H')&&p[2]>='0'&&p[2]<='7'){ + op->type=OP_BGPR; + op->reg=(p[2]-'0')*2+1; + op->regsfr=op->reg+0xf0; + }else if(p[0]=='#'){ + op->type=OP_IMM16; + p=skip(p+1); + if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);} + if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);} + if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);} + if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);} + if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);} + if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);} + if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);} + op->offset=parse_expr(&p); + simplify_expr(op->offset); +#if 0 + if(op->offset->type==NUM){ + taddr val=op->offset->c.val; + if(val>=0&&val<=7) + op->type=OP_IMM3; + else if(val>=0&&val<=15) + op->type=OP_IMM4; + else if(val>=0&&val<=127) + op->type=OP_IMM7; + else if(val>=0&&val<=255) + op->type=OP_IMM8; + } +#endif + }else if(*p=='['){ + p=skip(p+1); + if(*p=='-'){ + p=skip(p+1); + p=skip_reg(p,&op->reg); + p=skip(p); + if(*p!=']') + cpu_error(0); + if(op->reg<=3) + op->type=OP_PREDEC03; + else + op->type=OP_PREDEC; + }else{ + p=skip_reg(p,&op->reg); + p=skip(p); + if(*p=='+'){ + p=skip(p+1); + if(*p==']'){ + if(op->reg<=3) + op->type=OP_POSTINC03; + else + op->type=OP_POSTINC; + }else{ + if(*p!='#') + cpu_error(0); + p=skip(p+1); + op->offset=parse_expr(&p); + p=skip(p); + op->type=OP_REGDISP; + } + }else{ + if(op->reg<=3) + op->type=OP_REG03IND; + else + op->type=OP_REGIND; + } + if(*p!=']') + cpu_error(0); + } + }else{ + if(ISIDSTART(*p)){ + char *name=p; + hashdata data; + while((p==name||ISIDCHAR(*p))&&*p!='.') + p++; + if(find_namelen(sfrhash,name,p-name,&data)){ + sfr *sfr; + sfr=data.ptr; + if(sfr->flags&ISBIT){ + op->offset=number_expr(sfr->saddr); + op->type=OP_BADDR; + op->boffset=number_expr(sfr->boffset); + }else{ + if(requires==OP_SFR||requires==OP_BSFR||requires==OP_BWORD){ + op->offset=number_expr(sfr->saddr); + op->type=requires; + }else if(requires==OP_BADDR&&*p=='.'){ + op->offset=number_expr(sfr->saddr); + p=skip(p+1); + op->boffset=parse_expr(&p); + op->type=OP_BADDR; + }else if(requires==OP_ABS||requires==OP_BABS){ + op->type=requires; + op->offset=number_expr((2*sfr->saddr)+(sfr->laddr<<8)); + } + } + } + if(op->type==-1) + p=name; + } + if(op->type==-1){ + if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);} + if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);} + if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);} + if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);} + if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);} + if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);} + if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);} + op->offset=parse_expr(&p); + op->type=OP_ABS; + } + } + if(requires==op->type) + return 1; + if(requires==OP_BWORD&&op->type==OP_SFR) + return 1; + if(op->type==OP_IMM16&&(requires>=OP_IMM2&&requires<=OP_IMM16)) + return 1; + if(op->type==OP_PREDEC03&&requires==OP_PREDEC) + return 1; + if(op->type==OP_POSTINC03&&requires==OP_POSTINC) + return 1; + if(op->type==OP_REG03IND&&requires==OP_REGIND) + return 1; + if((requires==OP_SFR&&op->type==OP_GPR)|| + (requires==OP_BWORD&&op->type==OP_GPR)|| + (requires==OP_BWORD&&op->type==OP_BGPR)|| + (requires==OP_BSFR&&op->type==OP_BGPR)){ + op->offset=number_expr(op->regsfr); + return 1; + } + if(requires==OP_BSFR&&op->type==OP_BGPR) + return 1; + if(requires==OP_JADDR&&op->type==OP_ABS) + return 1; + if(requires==OP_BABS&&op->type==OP_ABS) + return 1; + /*FIXME*/ + return 0; +} + +static taddr reloffset(expr *tree,section *sec,taddr pc) +{ + symbol *sym; + int btype; + taddr val; + simplify_expr(tree); + if(tree->type==NUM){ + /* should we do it like this?? */ + val=tree->c.val; + }else{ + btype=find_base(tree,&sym,sec,pc); + if(btype!=BASE_OK||!LOCREF(sym)||sym->sec!=sec) + val=0xffff; + else{ + eval_expr(tree,&val,sec,pc); + val=val-pc; + } + } + return val; +} + +static taddr absoffset2(expr *tree,int mod,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask) +{ + taddr val; + if(mod==MOD_SOF){ + if(mask!=0xffffffff&&mask!=0xffff) cpu_error(5); + mask=0xffff; + } + if(mod==MOD_SEG){ + if(mask!=0xff&&mask!=0xffff&&mask!=0xffffffff) cpu_error(6); + mask<<=16; + } + if(mod==MOD_DPP0||mod==MOD_DPP1||mod==MOD_DPP2||mod==MOD_DPP3||mod==MOD_DPPX){ + if(mask!=0xffffffff&&mask!=0xffff) cpu_error(7); + mask=0x3fff; + } + if(!eval_expr(tree,&val,sec,pc)){ + taddr addend=val; + symbol *base; + if(find_base(tree,&base,sec,pc)!=BASE_OK){ + general_error(38); + return val; + } + if(mod==MOD_DPP1) val|=0x4000; + if(mod==MOD_DPP2) val|=0x8000; + if(mod==MOD_DPP3) val|=0xc000; + if(mod==MOD_DPPX){ + static int dpplen; + static char *dppname; + char *id=base->name; + symbol *dppsym; + size-=2; + if(strlen(id)+9>dpplen){ + myfree(dppname); + dppname=mymalloc(dpplen=strlen(id)+9); + } + strcpy(dppname,"___DPP_"); + strcat(dppname,id); + dppsym=new_import(dppname); + if(dppsym->type==EXPRESSION){ + if(!eval_expr(dppsym->expr,&val,0,0)) + ierror(0); + val<<=14; + }else{ + add_nreloc_masked(relocs,dppsym,0,REL_ABS,2,roffset+14,0x3); + } + } + add_nreloc_masked(relocs,base,addend,REL_ABS,size,roffset,mask); + return val; + } + val&=mask; + if(mod==MOD_DPPX) cpu_error(7); + if(mod==MOD_DPP1) val|=0x4000; + if(mod==MOD_DPP2) val|=0x8000; + if(mod==MOD_DPP3) val|=0xc000; + if(mod==MOD_SEG) val>>=16; + /*FIXME: range check */ +#if 1 + if(size==16) + return val&0xffff; + else + return val&((1<4) + cpu_error(3,2); + return val; + }else if(val<0||val>=(1<code; + taddr val; + /* choose one of jmpr/jmpa */ + if(c==JMP||(!notrans&&(c==JMPA||c==JMPR||c==JB||c==JNB))){ + val=reloffset(p->op[1]->offset,sec,pc); + if(val<-256||val>254||val%2){ + if(c==JB) return JNB|JMPCONV; + if(c==JNB) return JB|JMPCONV; + if(c==JMPA) return JMPA; + if(tojmpa) return JMPA; + if(p->op[0]->cc==0) + return JMPS; + else + return JMPR|JMPCONV; + }else{ + if(c==JB||c==JNB) + return c; + return JMPR; + } + } + /* choose between gpr,#imm3 and reg,#imm16 */ + if(mnemonics[c].operand_type[1]==OP_IMM3){ + if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){ + if(!strcmp(mnemonics[c].name,mnemonics[c+1].name)) + return c+1; + } + } + /* choose between gpr,#imm4 and reg,#imm16 */ + if(mnemonics[c].operand_type[1]==OP_IMM4){ + if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){ + if(!strcmp(mnemonics[c].name,mnemonics[c+1].name)) + return c+1; + } + } + return c; +} + +/* Convert an instruction into a DATA atom including relocations, + if necessary. */ +dblock *eval_instruction(instruction *p,section *sec,taddr pc) +{ + dblock *db=new_dblock(); + int opcode,c,jmpconv=0,osize; + unsigned long code; + char *d; + taddr val; + rlist *relocs=0; + operand *jmpaddr; + + c=translate(p,sec,pc); + if(c&JMPCONV){ jmpconv=1;c&=~JMPCONV;} + if((mnemonics[p->code].operand_type[0]==OP_GPR&&mnemonics[c].operand_type[0]==OP_SFR)|| + (mnemonics[p->code].operand_type[0]==OP_BGPR&&mnemonics[c].operand_type[0]==OP_BSFR)) + p->op[0]->offset=number_expr(p->op[0]->regsfr); + + + db->size=osize=mnemonics[c].ext.len*2; + if(jmpconv) db->size+=4; + db->data=mymalloc(db->size); + + opcode=mnemonics[c].ext.opcode; + switch(mnemonics[c].ext.encoding){ + case 0: + code=opcode<<16|(opcode>>8)<<8|opcode>>8; + break; + case 1: + code=opcode; + break; + case 2: + code=opcode|p->op[0]->reg<<4|p->op[1]->reg; + break; + case 3: + code=opcode|p->op[0]->reg|p->op[1]->reg<<4; + break; + case 4: + code=opcode|p->op[0]->reg<<4|p->op[1]->reg|8; + break; + case 5: + code=opcode|p->op[0]->reg<<4|p->op[1]->reg|12; + break; + case 6: + code=opcode|p->op[0]->reg<<4|absval(p->op[1]->offset,sec,pc,3); + break; + case 7: + /* fall through */ + case 8: + code=opcode<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,20,8)<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16); + break; + case 9: + code=opcode|p->op[0]->reg|absval(p->op[1]->offset,sec,pc,4)<<4; + break; + case 10: +/* rfi: reorder bmov operands */ + code=opcode<<16| + absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16| + absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8)<<0| + absoffset(p->op[1]->boffset,0,sec,pc,&relocs,24,4)<<12| + absoffset(p->op[0]->boffset,0,sec,pc,&relocs,28,4)<<8; + break; + case 11: + code=opcode|absoffset(p->op[0]->boffset,0,sec,pc,&relocs,0,4)<<12|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8); + break; + case 12: + code=opcode<<16| + absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16| + absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,16,8)<<8| + absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,24,8); + break; + case 13: + code=opcode<<16| + absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16| + absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,8)<<8| + absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,24,8); + break; + case 14: + code=opcode<<16|p->op[0]->cc<<20|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16); + break; + case 15: + code=opcode|p->op[0]->cc<<4|p->op[1]->reg; + break; + case 16: + val=((reloffset(p->op[0]->offset,sec,pc)-2)>>1)&255; + code=opcode|val; + break; + case 17: + if(p->op[0]->type==OP_CC){ + /* jmp cc_uc was converted to jmps */ + code=opcode<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,16,16,0xffff); + }else{ + code=opcode<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,16,16,0xffff); + } + break; + case 18: + /* fall through */ + case 19: + code=opcode<<16|0xf<<20|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16); + break; + case 20: + code=opcode|p->op[0]->reg<<4; + break; + case 21: + code=opcode|p->op[0]->reg<<4|p->op[0]->reg; + break; + case 22: + if(!jmpconv){ + val=((reloffset(p->op[1]->offset,sec,pc)-4)>>1)&255; + code=opcode<<16| + absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16| + absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12| + val; + }else{ + code=opcode<<16| + absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16| + absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12| + 2; + jmpaddr=p->op[1]; + } + break; + case 23: + if(!jmpconv){ + val=((reloffset(p->op[1]->offset,sec,pc)-2)>>1)&255; + code=opcode|p->op[0]->cc<<12|val; + }else{ + code=opcode|INVCC(p->op[0]->cc)<<12|2; + jmpaddr=p->op[1]; + } + break; + case 24: + code=opcode<<16|p->op[0]->reg<<20|p->op[1]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16); + break; + case 25: + code=opcode<<16|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16); + break; + case 26: + code=opcode|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8); + break; + case 27: + code=opcode|absval(p->op[0]->offset,sec,pc,7)<<1; + break; + case 28: + code=opcode<<16|p->op[0]->reg<<16|p->op[1]->reg<<20|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16); + break; + case 29: + code=opcode<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16); + break; + case 30: + code=opcode<<16|p->op[1]->reg<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16); + break; + case 31: + code=opcode|((absval(p->op[0]->offset,sec,pc,2)-1)<<4); + break; + case 32: + code=opcode|p->op[0]->reg|((absval(p->op[1]->offset,sec,pc,2)-1)<<4); + break; + case 34: + code=opcode<<16|((absval(p->op[1]->offset,sec,pc,2)-1)<<20)|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8); + break; + case 33: + default: + ierror(mnemonics[c].ext.encoding); + } + + d=db->data; + if(osize==4){ + *d++=code>>24; + *d++=code>>16; + *d++=code; + *d++=code>>8; + }else{ + *d++=code>>8; + *d++=code; + } + if(jmpconv){ + *d++=0xfa; + *d++=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,8+8*osize,8,0xffff0000); + val=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,16+8*osize,16,0xffff); + *d++=val>>8; + *d++=val; + } + db->relocs=relocs; + return db; +} + +/* Create a dblock (with relocs, if necessary) for size bits of data. */ +dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc) +{ + dblock *new=new_dblock(); + taddr val; + new->size=(bitsize+7)/8; + new->data=mymalloc(new->size); + if(op->type!=OP_ABS) + ierror(0); + if(bitsize!=8&&bitsize!=16&&bitsize!=32) + cpu_error(4); + val=absoffset(op->offset,op->mod,sec,pc,&new->relocs,0,bitsize); + if(bitsize==32){ + new->data[3]=val>>24; + new->data[2]=val>>16; + new->data[1]=val>>8; + new->data[0]=val; + }else if(bitsize==16){ + new->data[1]=val>>8; + new->data[0]=val; + }else + new->data[0]=val; + return new; +} + + +/* Calculate the size of the current instruction; must be identical + to the data created by eval_instruction. */ +size_t instruction_size(instruction *p,section *sec,taddr pc) +{ + int c=translate(p,sec,pc),add=0; + if(c&JMPCONV){ add=4;c&=~JMPCONV;} + return mnemonics[c].ext.len*2+add; +} + +operand *new_operand() +{ + operand *new=mymalloc(sizeof(*new)); + new->type=-1; + return new; +} + +/* return true, if initialization was successfull */ +int init_cpu() +{ + int i; + for(i=0;inext=first_sfr; + first_sfr=new; + } + new->flags=new->laddr=new->saddr=0; + new->boffset=0; + s=skip(s); + if(*s!=',') + cpu_error(0); + else + s=skip(s+1); + tree=parse_expr(&s); + simplify_expr(tree); + if(!tree||tree->type!=NUM) + cpu_error(0); + else + new->laddr=tree->c.val; + s=skip(s); + if(tree->c.val==0xfe||tree->c.val==0xf0){ + if(*s!=',') + cpu_error(0); + else + s=skip(s+1); + free_expr(tree); + tree=parse_expr(&s); + simplify_expr(tree); + if(!tree||tree->type!=NUM) + cpu_error(0); + else + new->saddr=tree->c.val; + free_expr(tree); + s=skip(s); + }else{ + if(tree->c.val>=0xfe00) + new->laddr=0xfe; + else + new->laddr=0xf0; + new->saddr=(tree->c.val-(new->laddr<<8))/2; + if((new->laddr<<8)+2*new->saddr!=tree->c.val) ierror(0); + free_expr(tree); + } + if(*s==','){ + s=skip(s+1); + tree=parse_expr(&s); + simplify_expr(tree); + new->boffset=tree->c.val; + new->flags|=ISBIT; + free_expr(tree); + } + return skip(s); + } + } + return merk; +} diff --git a/vasm-1/cpus/c16x/cpu.h b/vasm-1/cpus/c16x/cpu.h new file mode 100644 index 0000000..9b282dd --- /dev/null +++ b/vasm-1/cpus/c16x/cpu.h @@ -0,0 +1,88 @@ +/* cpu.h c16x/st10 cpu-description header-file */ +/* (c) in 2002 by Volker Barthelmann */ + + +/* maximum number of operands in one mnemonic */ +#define MAX_OPERANDS 3 + +/* maximum number of mnemonic-qualifiers per mnemonic */ +#define MAX_QUALIFIERS 0 + +/* maximum number of additional command-line-flags for this cpu */ + +/* data type to represent a target-address */ +typedef int32_t taddr; +typedef uint32_t utaddr; + +#define LITTLEENDIAN 1 +#define BIGENDIAN 0 +#define VASM_CPU_C16X 1 + +/* minimum instruction alignment */ +#define INST_ALIGN 2 + +/* default alignment for n-bit data */ +#define DATA_ALIGN(n) ((n)<=8?1:2) + +/* operand class for n-bit data definitions */ +#define DATA_OPERAND(n) OP_ABS + +#define cc reg + +/* type to store each operand */ +typedef struct { + int type; + int mod; + int reg,regsfr; /* also cc and boff */ + expr *offset,*boffset; +} operand; + +/* operand-types */ +#define OP_GPR 1 +#define OP_BGPR 2 +#define OP_SFR 3 +#define OP_BSFR 4 +#define OP_ABS 5 +#define OP_SEG OP_ABS +#define OP_BABS 6 +#define OP_REGDISP 7 +#define OP_REGIND 8 +#define OP_REG03IND 9 +#define OP_BWORD 10 +#define OP_BADDR 11 +#define OP_IMM2 12 +#define OP_IMM3 13 +#define OP_IMM4 14 +#define OP_IMM7 15 +#define OP_IMM8 16 +#define OP_IMM16 17 +#define OP_CC 18 +#define OP_REL 19 +#define OP_JADDR 20 +#define OP_POSTINC03 21 +#define OP_PREDEC03 22 +#define OP_POSTINC 23 +#define OP_PREDEC 24 +#define OP_PROTECTED 0 + +/* mod types */ +#define MOD_SOF 1 +#define MOD_SEG 2 +#define MOD_DPP0 3 +#define MOD_DPP1 4 +#define MOD_DPP2 5 +#define MOD_DPP3 6 +#define MOD_DPPX 7 + +#define CPU_C166 1 +#define CPU_C167 2 +#define CPU_ALL (-1) + +typedef struct { + unsigned int len; + unsigned int opcode; + unsigned int match; + unsigned int lose; + unsigned int encoding; + unsigned int available; +} mnemonic_extension; diff --git a/vasm-1/cpus/c16x/cpu_errors.h b/vasm-1/cpus/c16x/cpu_errors.h new file mode 100644 index 0000000..cffdaad --- /dev/null +++ b/vasm-1/cpus/c16x/cpu_errors.h @@ -0,0 +1,8 @@ + "illegal operand",ERROR, + "word register expected",ERROR, + "",ERROR, + "value does not find in %d bits",WARNING, + "data size not supported",ERROR, + "illegal use of SOF",WARNING, + "illegal use of SEG",WARNING, + "illegal use of DPP prefix",WARNING, diff --git a/vasm-1/cpus/c16x/opcodes.h b/vasm-1/cpus/c16x/opcodes.h new file mode 100644 index 0000000..5b546be --- /dev/null +++ b/vasm-1/cpus/c16x/opcodes.h @@ -0,0 +1,233 @@ +"add",OP_GPR,OP_GPR,0,1,0x0000,0x0000,0xff00,2,CPU_ALL, +"add",OP_GPR,OP_REG03IND,0,1,0x0800,0x0808,0xf704,4,CPU_ALL, +"add",OP_GPR,OP_POSTINC03,0,1,0x0800,0x080c,0xf700,5,CPU_ALL, +"add",OP_GPR,OP_IMM3,0,1,0x0800,0x0800,0xf708,6,CPU_ALL, +"add",OP_SFR,OP_IMM16,0,2,0x0600,0x0600,0xf900,7,CPU_ALL, +"add",OP_SFR,OP_ABS,0,2,0x0200,0x0200,0xfd00,8,CPU_ALL, +"add",OP_ABS,OP_SFR,0,2,0x0400,0x0400,0xfb00,29,CPU_ALL, +"addb",OP_BGPR,OP_BGPR,0,1,0x0100,0x0100,0xfe00,2,CPU_ALL, +"addb",OP_BGPR,OP_REG03IND,0,1,0x0900,0x0908,0xf604,4,CPU_ALL, +"addb",OP_BGPR,OP_POSTINC03,0,1,0x0900,0x090c,0xf600,5,CPU_ALL, +"addb",OP_BGPR,OP_IMM3,0,1,0x0900,0x0900,0xf608,6,CPU_ALL, +"addb",OP_BSFR,OP_IMM16,0,2,0x0700,0x0700,0xf800,7,CPU_ALL, +"addb",OP_BSFR,OP_BABS,0,2,0x0300,0x0300,0xfc00,8,CPU_ALL, +"addb",OP_BABS,OP_BSFR,0,2,0x0500,0x0500,0xfa00,29,CPU_ALL, +"addc",OP_GPR,OP_GPR,0,1,0x1000,0x1000,0xef00,2,CPU_ALL, +"addc",OP_GPR,OP_REG03IND,0,1,0x1800,0x1808,0xe704,4,CPU_ALL, +"addc",OP_GPR,OP_POSTINC03,0,1,0x1800,0x180c,0xe700,5,CPU_ALL, +"addc",OP_GPR,OP_IMM3,0,1,0x1800,0x1800,0xe708,6,CPU_ALL, +"addc",OP_SFR,OP_IMM16,0,2,0x1600,0x1600,0xe900,7,CPU_ALL, +"addc",OP_SFR,OP_ABS,0,2,0x1200,0x1200,0xed00,8,CPU_ALL, +"addc",OP_ABS,OP_SFR,0,2,0x1400,0x1400,0xeb00,29,CPU_ALL, +"addcb",OP_BGPR,OP_BGPR,0,1,0x1100,0x1100,0xee00,2,CPU_ALL, +"addcb",OP_BGPR,OP_REG03IND,0,1,0x1900,0x1908,0xe604,4,CPU_ALL, +"addcb",OP_BGPR,OP_POSTINC03,0,1,0x1900,0x190c,0xe600,5,CPU_ALL, +"addcb",OP_BGPR,OP_IMM3,0,1,0x1900,0x1900,0xe608,6,CPU_ALL, +"addcb",OP_BSFR,OP_IMM16,0,2,0x1700,0x1700,0xe800,7,CPU_ALL, +"addcb",OP_BSFR,OP_BABS,0,2,0x1300,0x1300,0xec00,8,CPU_ALL, +"addcb",OP_BABS,OP_BSFR,0,2,0x1500,0x1500,0xea00,29,CPU_ALL, +"and",OP_GPR,OP_GPR,0,1,0x6000,0x6000,0x9f00,2,CPU_ALL, +"and",OP_GPR,OP_REG03IND,0,1,0x6800,0x6808,0x9704,4,CPU_ALL, +"and",OP_GPR,OP_POSTINC03,0,1,0x6800,0x680c,0x9700,5,CPU_ALL, +"and",OP_GPR,OP_IMM3,0,1,0x6800,0x6800,0x9708,6,CPU_ALL, +"and",OP_SFR,OP_IMM16,0,2,0x6600,0x6600,0x9900,7,CPU_ALL, +"and",OP_SFR,OP_ABS,0,2,0x6200,0x6200,0x9d00,8,CPU_ALL, +"and",OP_ABS,OP_SFR,0,2,0x6400,0x6400,0x9b00,29,CPU_ALL, +"andb",OP_BGPR,OP_BGPR,0,1,0x6100,0x6100,0x9e00,2,CPU_ALL, +"andb",OP_BGPR,OP_REG03IND,0,1,0x6900,0x6908,0x9604,4,CPU_ALL, +"andb",OP_BGPR,OP_POSTINC03,0,1,0x6900,0x690c,0x9600,5,CPU_ALL, +"andb",OP_BGPR,OP_IMM3,0,1,0x6900,0x6900,0x9608,6,CPU_ALL, +"andb",OP_BSFR,OP_IMM16,0,2,0x6700,0x6700,0x9800,7,CPU_ALL, +"andb",OP_BSFR,OP_BABS,0,2,0x6300,0x6300,0x9c00,8,CPU_ALL, +"andb",OP_BABS,OP_BSFR,0,2,0x6500,0x6500,0x9a00,29,CPU_ALL, +"ashr",OP_GPR,OP_GPR,0,1,0xac00,0xac00,0x5300,2,CPU_ALL, +"ashr",OP_GPR,OP_IMM4,0,1,0xbc00,0xbc00,0x4300,9,CPU_ALL, +"atomic",OP_IMM3,0,0,1,0xd100,0xd100,0x2ecf,31,CPU_C167, +"band",OP_BADDR,OP_BADDR,0,2,0x6a00,0x6a00,0x9500,10,CPU_ALL, +"bclr",OP_BADDR,0,0,1,0x0e00,0x0e00,0x0100,11,CPU_ALL, +"bcmp",OP_BADDR,OP_BADDR,0,2,0x2a00,0x2a00,0xd500,10,CPU_ALL, +"bfldh",OP_BWORD,OP_IMM8,OP_IMM8,2,0x1a00,0x1a00,0xe500,12,CPU_ALL, +"bfldl",OP_BWORD,OP_IMM8,OP_IMM8,2,0x0a00,0x0a00,0xf500,13,CPU_ALL, +"bmov",OP_BADDR,OP_BADDR,0,2,0x4a00,0x4a00,0xb500,10,CPU_ALL, +"bmovn",OP_BADDR,OP_BADDR,0,2,0x3a00,0x3a00,0xc500,10,CPU_ALL, +"bor",OP_BADDR,OP_BADDR,0,2,0x5a00,0x5a00,0xa500,10,CPU_ALL, +"bset",OP_BADDR,0,0,1,0x0f00,0x0f00,0x0000,11,CPU_ALL, +"bxor",OP_BADDR,OP_BADDR,0,2,0x7a00,0x7a00,0x8500,10,CPU_ALL, +"call",OP_REL,0,0,1,0xbb00,0xbb00,0x4400,16,CPU_ALL, +"calla",OP_CC,OP_JADDR,0,2,0xca00,0xca00,0x350f,14,CPU_ALL, +"calli",OP_CC,OP_REGIND,0,1,0xab00,0xab00,0x5400,15,CPU_ALL, +"callr",OP_REL,0,0,1,0xbb00,0xbb00,0x4400,16,CPU_ALL, +"calls",OP_JADDR,0,0,2,0xda00,0xda00,0x2500,17,CPU_ALL, +"cmp",OP_GPR,OP_GPR,0,1,0x4000,0x4000,0xbf00,2,CPU_ALL, +"cmp",OP_GPR,OP_REG03IND,0,1,0x4800,0x4808,0xb704,4,CPU_ALL, +"cmp",OP_GPR,OP_POSTINC03,0,1,0x4800,0x480c,0xb700,5,CPU_ALL, +"cmp",OP_GPR,OP_IMM3,0,1,0x4800,0x4800,0xb708,6,CPU_ALL, +"cmp",OP_SFR,OP_IMM16,0,2,0x4600,0x4600,0xb900,7,CPU_ALL, +"cmp",OP_SFR,OP_ABS,0,2,0x4200,0x4200,0xbd00,8,CPU_ALL, +"cmpb",OP_BGPR,OP_BGPR,0,1,0x4100,0x4100,0xbe00,2,CPU_ALL, +"cmpb",OP_BGPR,OP_REG03IND,0,1,0x4900,0x4908,0xb604,4,CPU_ALL, +"cmpb",OP_BGPR,OP_POSTINC03,0,1,0x4900,0x490c,0xb600,5,CPU_ALL, +"cmpb",OP_BGPR,OP_IMM3,0,1,0x4900,0x4900,0xb608,6,CPU_ALL, +"cmpb",OP_BSFR,OP_IMM16,0,2,0x4700,0x4700,0xb800,7,CPU_ALL, +"cmpb",OP_BSFR,OP_BABS,0,2,0x4300,0x4300,0xbc00,8,CPU_ALL, +"cmpd1",OP_GPR,OP_IMM4,0,1,0xa000,0xa000,0x5f00,9,CPU_ALL, +"cmpd1",OP_GPR,OP_IMM16,0,2,0xa600,0xa6f0,0x5900,18,CPU_ALL, +"cmpd1",OP_GPR,OP_ABS,0,2,0xa200,0xa2f0,0x5d00,19,CPU_ALL, +"cmpd2",OP_GPR,OP_IMM4,0,1,0xb000,0xb000,0x4f00,9,CPU_ALL, +"cmpd2",OP_GPR,OP_IMM16,0,2,0xb600,0xb6f0,0x4900,18,CPU_ALL, +"cmpd2",OP_GPR,OP_ABS,0,2,0xb200,0xb2f0,0x4d00,19,CPU_ALL, +"cmpi1",OP_GPR,OP_IMM4,0,1,0x8000,0x8000,0x7f00,9,CPU_ALL, +"cmpi1",OP_GPR,OP_IMM16,0,2,0x8600,0x86f0,0x7900,18,CPU_ALL, +"cmpi1",OP_GPR,OP_ABS,0,2,0x8200,0x82f0,0x7d00,19,CPU_ALL, +"cmpi2",OP_GPR,OP_IMM4,0,1,0x9000,0x9000,0x6f00,9,CPU_ALL, +"cmpi2",OP_GPR,OP_IMM16,0,2,0x9600,0x96f0,0x6900,18,CPU_ALL, +"cmpi2",OP_GPR,OP_ABS,0,2,0x9200,0x92f0,0x6d00,19,CPU_ALL, +"cpl",OP_GPR,0,0,1,0x9100,0x9100,0x6e0f,20,CPU_ALL, +"cplb",OP_BGPR,0,0,1,0xb100,0xb100,0x4e0f,20,CPU_ALL, +"diswdt",OP_PROTECTED,0,0,2,0xa55a,0xa55a,0x5aa5,0,CPU_ALL, +"div",OP_GPR,0,0,1,0x4b00,0x4b00,0xb400,21,CPU_ALL, +"divl",OP_GPR,0,0,1,0x6b00,0x6b00,0x9400,21,CPU_ALL, +"divlu",OP_GPR,0,0,1,0x7b00,0x7b00,0x8400,21,CPU_ALL, +"divu",OP_GPR,0,0,1,0x5b00,0x5b00,0xa400,21,CPU_ALL, +"einit",OP_PROTECTED,0,0,2,0xb54a,0xb54a,0x4ab5,0,CPU_ALL, + +"extp",OP_GPR,OP_IMM3,0,1,0xdc40,0xdc40,0x2380,32,CPU_C167, +"extp",OP_IMM16,OP_IMM3,0,2,0xd740,0xd740,0x288f,33,CPU_C167, +"extr",OP_IMM3,0,0,1,0xd180,0xd180,0x2e4f,31,CPU_C167, +"extpr",OP_GPR,OP_IMM3,0,1,0xdcc0,0xdcc0,0x2300,32,CPU_C167, +"extpr",OP_IMM16,OP_IMM3,0,2,0xd7c0,0xd7c0,0x280f,33,CPU_C167, +"exts",OP_GPR,OP_IMM3,0,1,0xdc00,0xdc00,0x23c0,32,CPU_C167, +"exts",OP_IMM8,OP_IMM3,0,2,0xd700,0xd700,0x28cf,34,CPU_C167, +"extsr",OP_GPR,OP_IMM3,0,1,0xdc80,0xdc80,0x2340,32,CPU_C167, +"extsr",OP_IMM8,OP_IMM3,0,2,0xd780,0xd780,0x284f,34,CPU_C167, +"idle",OP_PROTECTED,0,0,2,0x8778,0x8778,0x7887,0,CPU_ALL, +"jb",OP_BADDR,OP_REL,0,2,0x8a00,0x8a00,0x7500,22,CPU_ALL, +"jbc",OP_BADDR,OP_REL,0,2,0xaa00,0xaa00,0x5500,22,CPU_ALL, +"jmp",OP_CC,OP_REL,0,1,0x0d00,0x0d00,0x0200,23,CPU_ALL, +"jmpa",OP_CC,OP_JADDR,0,2,0xea00,0xea00,0x150f,14,CPU_ALL, +"jmpi",OP_CC,OP_REGIND,0,1,0x9c00,0x9c00,0x6300,15,CPU_ALL, +"jmpr",OP_CC,OP_REL,0,1,0x0d00,0x0d00,0x0200,23,CPU_ALL, +"jmps",OP_JADDR,0,0,2,0xfa00,0xfa00,0x0500,17,CPU_ALL, +"jnb",OP_BADDR,OP_REL,0,2,0x9a00,0x9a00,0x6500,22,CPU_ALL, +"jnbs",OP_BADDR,OP_REL,0,2,0xba00,0xba00,0x4500,22,CPU_ALL, +"mov",OP_GPR,OP_GPR,0,1,0xf000,0xf000,0x0f00,2,CPU_ALL, +"mov",OP_GPR,OP_IMM4,0,1,0xe000,0xe000,0x1f00,9,CPU_ALL, +"mov",OP_SFR,OP_IMM16,0,2,0xe600,0xe600,0x1900,7,CPU_ALL, +"mov",OP_GPR,OP_REGIND,0,1,0xa800,0xa800,0x5700,2,CPU_ALL, +"mov",OP_GPR,OP_POSTINC,0,1,0x9800,0x9800,0x6700,2,CPU_ALL, +"mov",OP_REGIND,OP_GPR,0,1,0xb800,0xb800,0x4700,3,CPU_ALL, +"mov",OP_PREDEC,OP_GPR,0,1,0x8800,0x8800,0x7700,3,CPU_ALL, +"mov",OP_REGIND,OP_REGIND,0,1,0xc800,0xc800,0x3700,2,CPU_ALL, +"mov",OP_POSTINC,OP_REGIND,0,1,0xd800,0xd800,0x2700,2,CPU_ALL, +"mov",OP_REGIND,OP_POSTINC,0,1,0xe800,0xe800,0x1700,2,CPU_ALL, +"mov",OP_GPR,OP_REGDISP,0,2,0xd400,0xd400,0x2b00,24,CPU_ALL, +"mov",OP_REGDISP,OP_GPR,0,2,0xc400,0xc400,0x3b00,28,CPU_ALL, +"mov",OP_REGIND,OP_ABS,0,2,0x8400,0x8400,0x7bf0,25,CPU_ALL, +"mov",OP_ABS,OP_REGIND,0,2,0x9400,0x9400,0x6bf0,30,CPU_ALL, +"mov",OP_SFR,OP_ABS,0,2,0xf200,0xf200,0x0d00,8,CPU_ALL, +"mov",OP_ABS,OP_SFR,0,2,0xf600,0xf600,0x0900,29,CPU_ALL, +"movb",OP_BGPR,OP_BGPR,0,1,0xf100,0xf100,0x0e00,2,CPU_ALL, +"movb",OP_BGPR,OP_IMM4,0,1,0xe100,0xe100,0x1e00,9,CPU_ALL, +"movb",OP_BSFR,OP_IMM16,0,2,0xe700,0xe700,0x1800,7,CPU_ALL, +"movb",OP_BGPR,OP_REGIND,0,1,0xa900,0xa900,0x5600,2,CPU_ALL, +"movb",OP_BGPR,OP_POSTINC,0,1,0x9900,0x9900,0x6600,2,CPU_ALL, +"movb",OP_REGIND,OP_BGPR,0,1,0xb900,0xb900,0x4600,3,CPU_ALL, +"movb",OP_PREDEC,OP_BGPR,0,1,0x8900,0x8900,0x7600,3,CPU_ALL, +"movb",OP_REGIND,OP_REGIND,0,1,0xc900,0xc900,0x3600,2,CPU_ALL, +"movb",OP_POSTINC,OP_REGIND,0,1,0xd900,0xd900,0x2600,2,CPU_ALL, +"movb",OP_REGIND,OP_POSTINC,0,1,0xe900,0xe900,0x1600,2,CPU_ALL, +"movb",OP_BGPR,OP_REGDISP,0,2,0xf400,0xf400,0x0b00,24,CPU_ALL, +"movb",OP_REGDISP,OP_BGPR,0,2,0xe400,0xe400,0x1b00,28,CPU_ALL, +"movb",OP_REGIND,OP_BABS,0,2,0xa400,0xa400,0x5bf0,25,CPU_ALL, +"movb",OP_BABS,OP_REGIND,0,2,0xb400,0xb400,0x4bf0,30,CPU_ALL, +"movb",OP_BSFR,OP_BABS,0,2,0xf300,0xf300,0x0c00,8,CPU_ALL, +"movb",OP_BABS,OP_BSFR,0,2,0xf700,0xf700,0x0800,29,CPU_ALL, +"movbs",OP_GPR,OP_BGPR,0,1,0xd000,0xd000,0x2f00,3,CPU_ALL, +"movbs",OP_SFR,OP_BABS,0,2,0xd200,0xd200,0x2d00,8,CPU_ALL, +"movbs",OP_ABS,OP_BSFR,0,2,0xd500,0xd500,0x2a00,29,CPU_ALL, +"movbz",OP_GPR,OP_BGPR,0,1,0xc000,0xc000,0x3f00,3,CPU_ALL, +"movbz",OP_SFR,OP_BABS,0,2,0xc200,0xc200,0x3d00,8,CPU_ALL, +"movbz",OP_ABS,OP_BSFR,0,2,0xc500,0xc500,0x3a00,29,CPU_ALL, +"mul",OP_GPR,OP_GPR,0,1,0x0b00,0x0b00,0xf400,2,CPU_ALL, +"mulu",OP_GPR,OP_GPR,0,1,0x1b00,0x1b00,0xe400,2,CPU_ALL, +"neg",OP_GPR,0,0,1,0x8100,0x8100,0x7e0f,20,CPU_ALL, +"negb",OP_BGPR,0,0,1,0xa100,0xa100,0x5e0f,20,CPU_ALL, +"nop",0,0,0,1,0xcc00,0xcc00,0x33ff,1,CPU_ALL, +"or",OP_GPR,OP_GPR,0,1,0x7000,0x7000,0x8f00,2,CPU_ALL, +"or",OP_GPR,OP_REG03IND,0,1,0x7800,0x7808,0x8704,4,CPU_ALL, +"or",OP_GPR,OP_POSTINC03,0,1,0x7800,0x780c,0x8700,5,CPU_ALL, +"or",OP_GPR,OP_IMM3,0,1,0x7800,0x7800,0x8708,6,CPU_ALL, +"or",OP_SFR,OP_IMM16,0,2,0x7600,0x7600,0x8900,7,CPU_ALL, +"or",OP_SFR,OP_ABS,0,2,0x7200,0x7200,0x8d00,8,CPU_ALL, +"or",OP_ABS,OP_SFR,0,2,0x7400,0x7400,0x8b00,29,CPU_ALL, +"orb",OP_BGPR,OP_BGPR,0,1,0x7100,0x7100,0x8e00,2,CPU_ALL, +"orb",OP_BGPR,OP_REG03IND,0,1,0x7900,0x7908,0x8604,4,CPU_ALL, +"orb",OP_BGPR,OP_POSTINC03,0,1,0x7900,0x790c,0x8600,5,CPU_ALL, +"orb",OP_BGPR,OP_IMM3,0,1,0x7900,0x7900,0x8608,6,CPU_ALL, +"orb",OP_BSFR,OP_IMM16,0,2,0x7700,0x7700,0x8800,7,CPU_ALL, +"orb",OP_BSFR,OP_BABS,0,2,0x7300,0x7300,0x8c00,8,CPU_ALL, +"orb",OP_BABS,OP_BSFR,0,2,0x7500,0x7500,0x8a00,29,CPU_ALL, +"pcall",OP_SFR,OP_JADDR,0,2,0xe200,0xe200,0x1d00,8,CPU_ALL, +"pop",OP_SFR,0,0,1,0xfc00,0xfc00,0x0300,26,CPU_ALL, +"prior",OP_GPR,OP_GPR,0,1,0x2b00,0x2b00,0xd400,2,CPU_ALL, +"push",OP_SFR,0,0,1,0xec00,0xec00,0x1300,26,CPU_ALL, +"pwrdn",OP_PROTECTED,0,0,2,0x9768,0x9768,0x6897,0,CPU_ALL, +"ret",0,0,0,1,0xcb00,0xcb00,0x34ff,1,CPU_ALL, +"reti",0,0,0,1,0xfb88,0xfb88,0x0477,1,CPU_ALL, +"retp",OP_SFR,0,0,1,0xeb00,0xeb00,0x1400,26,CPU_ALL, +"rets",0,0,0,1,0xdb00,0xdb00,0x24ff,1,CPU_ALL, +"rol",OP_GPR,OP_GPR,0,1,0x0c00,0x0c00,0xf300,2,CPU_ALL, +"rol",OP_GPR,OP_IMM4,0,1,0x1c00,0x1c00,0xe300,9,CPU_ALL, +"ror",OP_GPR,OP_GPR,0,1,0x2c00,0x2c00,0xd300,2,CPU_ALL, +"ror",OP_GPR,OP_IMM4,0,1,0x3c00,0x3c00,0xc300,9,CPU_ALL, +"scxt",OP_SFR,OP_IMM16,0,2,0xc600,0xc600,0x3900,7,CPU_ALL, +"scxt",OP_SFR,OP_ABS,0,2,0xd600,0xd600,0x2900,8,CPU_ALL, +"shl",OP_GPR,OP_GPR,0,1,0x4c00,0x4c00,0xb300,2,CPU_ALL, +"shl",OP_GPR,OP_IMM4,0,1,0x5c00,0x5c00,0xa300,9,CPU_ALL, +"shr",OP_GPR,OP_GPR,0,1,0x6c00,0x6c00,0x9300,2,CPU_ALL, +"shr",OP_GPR,OP_IMM4,0,1,0x7c00,0x7c00,0x8300,9,CPU_ALL, +"srst",OP_PROTECTED,0,0,2,0xb748,0xb748,0x48b7,0,CPU_ALL, +"srvwdt",OP_PROTECTED,0,0,2,0xa758,0xa758,0x58a7,0,CPU_ALL, +"sub",OP_GPR,OP_GPR,0,1,0x2000,0x2000,0xdf00,2,CPU_ALL, +"sub",OP_GPR,OP_REG03IND,0,1,0x2800,0x2808,0xd704,4,CPU_ALL, +"sub",OP_GPR,OP_POSTINC03,0,1,0x2800,0x280c,0xd700,5,CPU_ALL, +"sub",OP_GPR,OP_IMM3,0,1,0x2800,0x2800,0xd708,6,CPU_ALL, +"sub",OP_SFR,OP_IMM16,0,2,0x2600,0x2600,0xd900,7,CPU_ALL, +"sub",OP_SFR,OP_ABS,0,2,0x2200,0x2200,0xdd00,8,CPU_ALL, +"sub",OP_ABS,OP_SFR,0,2,0x2400,0x2400,0xdb00,29,CPU_ALL, +"subb",OP_BGPR,OP_BGPR,0,1,0x2100,0x2100,0xde00,2,CPU_ALL, +"subb",OP_BGPR,OP_REG03IND,0,1,0x2900,0x2908,0xd604,4,CPU_ALL, +"subb",OP_BGPR,OP_POSTINC03,0,1,0x2900,0x290c,0xd600,5,CPU_ALL, +"subb",OP_BGPR,OP_IMM3,0,1,0x2900,0x2900,0xd608,6,CPU_ALL, +"subb",OP_BSFR,OP_IMM16,0,2,0x2700,0x2700,0xd800,7,CPU_ALL, +"subb",OP_BSFR,OP_BABS,0,2,0x2300,0x2300,0xdc00,8,CPU_ALL, +"subb",OP_BABS,OP_BSFR,0,2,0x2500,0x2500,0xda00,29,CPU_ALL, +"subc",OP_GPR,OP_GPR,0,1,0x3000,0x3000,0xcf00,2,CPU_ALL, +"subc",OP_GPR,OP_REG03IND,0,1,0x3800,0x3808,0xc704,4,CPU_ALL, +"subc",OP_GPR,OP_POSTINC03,0,1,0x3800,0x380c,0xc700,5,CPU_ALL, +"subc",OP_GPR,OP_IMM3,0,1,0x3800,0x3800,0xc708,6,CPU_ALL, +"subc",OP_SFR,OP_IMM16,0,2,0x3600,0x3600,0xc900,7,CPU_ALL, +"subc",OP_SFR,OP_ABS,0,2,0x3200,0x3200,0xcd00,8,CPU_ALL, +"subc",OP_ABS,OP_SFR,0,2,0x3400,0x3400,0xcb00,29,CPU_ALL, +"subcb",OP_BGPR,OP_BGPR,0,1,0x3100,0x3100,0xce00,2,CPU_ALL, +"subcb",OP_BGPR,OP_REG03IND,0,1,0x3900,0x3908,0xc604,4,CPU_ALL, +"subcb",OP_BGPR,OP_POSTINC03,0,1,0x3900,0x390c,0xc600,5,CPU_ALL, +"subcb",OP_BGPR,OP_IMM3,0,1,0x3900,0x3900,0xc608,6,CPU_ALL, +"subcb",OP_BSFR,OP_IMM16,0,2,0x3700,0x3700,0xc800,7,CPU_ALL, +"subcb",OP_BSFR,OP_BABS,0,2,0x3300,0x3300,0xcc00,8,CPU_ALL, +"subcb",OP_BABS,OP_BSFR,0,2,0x3500,0x3500,0xca00,29,CPU_ALL, +"trap",OP_IMM7,0,0,1,0x9b00,0x9b00,0x6401,27,CPU_ALL, +"xor",OP_GPR,OP_GPR,0,1,0x5000,0x5000,0xaf00,2,CPU_ALL, +"xor",OP_GPR,OP_REG03IND,0,1,0x5800,0x5808,0xa704,4,CPU_ALL, +"xor",OP_GPR,OP_POSTINC03,0,1,0x5800,0x580c,0xa700,5,CPU_ALL, +"xor",OP_GPR,OP_IMM3,0,1,0x5800,0x5800,0xa708,6,CPU_ALL, +"xor",OP_SFR,OP_IMM16,0,2,0x5600,0x5600,0xa900,7,CPU_ALL, +"xor",OP_SFR,OP_ABS,0,2,0x5200,0x5200,0xad00,8,CPU_ALL, +"xor",OP_ABS,OP_SFR,0,2,0x5400,0x5400,0xab00,29,CPU_ALL, +"xorb",OP_BGPR,OP_BGPR,0,1,0x5100,0x5100,0xae00,2,CPU_ALL, +"xorb",OP_BGPR,OP_REG03IND,0,1,0x5900,0x5908,0xa604,4,CPU_ALL, +"xorb",OP_BGPR,OP_POSTINC03,0,1,0x5900,0x590c,0xa600,5,CPU_ALL, +"xorb",OP_BGPR,OP_IMM3,0,1,0x5900,0x5900,0xa608,6,CPU_ALL, +"xorb",OP_BSFR,OP_IMM16,0,2,0x5700,0x5700,0xa800,7,CPU_ALL, +"xorb",OP_BSFR,OP_BABS,0,2,0x5300,0x5300,0xac00,8,CPU_ALL, +"xorb",OP_BABS,OP_BSFR,0,2,0x5500,0x5500,0xaa00,29,CPU_ALL, diff --git a/vasm-1/cpus/jagrisc/cpu.c b/vasm-1/cpus/jagrisc/cpu.c new file mode 100644 index 0000000..dbe2621 --- /dev/null +++ b/vasm-1/cpus/jagrisc/cpu.c @@ -0,0 +1,616 @@ +/* + * cpu.c Jaguar RISC cpu description file + * (c) in 2014-2017 by Frank Wille + */ + +#include "vasm.h" + +mnemonic mnemonics[] = { +#include "opcodes.h" +}; +int mnemonic_cnt = sizeof(mnemonics) / sizeof(mnemonics[0]); + +char *cpu_copyright = "vasm Jaguar RISC cpu backend 0.4c (c) 2014-2017 Frank Wille"; +char *cpuname = "jagrisc"; +int bitsperbyte = 8; +int bytespertaddr = 4; + +int jag_big_endian = 1; /* defaults to big-endian (Atari Jaguar 68000) */ + +static uint8_t cpu_type = GPU|DSP; +static int OC_MOVEI,OC_UNPACK; + +/* condition codes */ +static regsym cc_regsyms[] = { + {"T", RTYPE_CC, 0, 0x00}, + {"NE", RTYPE_CC, 0, 0x01}, + {"EQ", RTYPE_CC, 0, 0x02}, + {"CC", RTYPE_CC, 0, 0x04}, + {"HI", RTYPE_CC, 0, 0x05}, + {"CS", RTYPE_CC, 0, 0x08}, + {"PL", RTYPE_CC, 0, 0x14}, + {"MI", RTYPE_CC, 0, 0x18}, + {"t", RTYPE_CC, 0, 0x00}, + {"ne", RTYPE_CC, 0, 0x01}, + {"eq", RTYPE_CC, 0, 0x02}, + {"cc", RTYPE_CC, 0, 0x04}, + {"hi", RTYPE_CC, 0, 0x05}, + {"cs", RTYPE_CC, 0, 0x08}, + {"pl", RTYPE_CC, 0, 0x14}, + {"mi", RTYPE_CC, 0, 0x18}, + {NULL, 0, 0, 0} +}; + + +int init_cpu(void) +{ + int i; + regsym *r; + + for (i=0; ireg_name!=NULL; r++) + add_regsym(r); + + return 1; +} + + +int cpu_args(char *p) +{ + if (!strncmp(p,"-m",2)) { + p += 2; + if (!stricmp(p,"gpu") || !stricmp(p,"tom")) + cpu_type = GPU; + else if (!stricmp(p,"dsp") || !stricmp(p,"jerry")) + cpu_type = DSP; + else if (!strcmp(p,"any")) + cpu_type = GPU|DSP; + else + return 0; + } + else if (!strcmp(p,"-big")) + jag_big_endian = 1; + else if (!strcmp(p,"-little")) + jag_big_endian = 0; + else + return 0; + + return 1; +} + + +static int parse_reg(char **p) +{ + int reg = -1; + char *rp = skip(*p); + char *s; + + if (s = skip_identifier(rp)) { + regsym *sym = find_regsym(rp,s-rp); + + if (sym!=NULL && sym->reg_type==RTYPE_R) { + reg = sym->reg_num; + } + else if (toupper((unsigned char)*rp++) == 'R') { + if (sscanf(rp,"%d",®)!=1 || reg<0 || reg>31) + reg = -1; + } + + if (reg >= 0) + *p = s; + } + + return reg; +} + + +static expr *parse_cc(char **p) +{ + char *end; + + *p = skip(*p); + + if (end = skip_identifier(*p)) { + regsym *sym = find_regsym(*p,end-*p); + + if (sym!=NULL && sym->reg_type==RTYPE_CC) { + *p = end; + return number_expr((taddr)sym->reg_num); + } + } + + /* otherwise the condition code is any expression */ + return parse_expr(p); +} + + +static void jagswap32(char *d,int32_t w) +/* write a 32-bit word with swapped halfs (Jaguar MOVEI) */ +{ + if (jag_big_endian) { + *d++ = (w >> 8) & 0xff; + *d++ = w & 0xff; + *d++ = (w >> 24) & 0xff; + *d = (w >> 16) & 0xff; + } + else { + /* @@@ Need to verify this! */ + *d++ = w & 0xff; + *d++ = (w >> 8) & 0xff; + *d++ = (w >> 16) & 0xff; + *d = (w >> 24) & 0xff; + } +} + + +char *parse_cpu_special(char *start) +/* parse cpu-specific directives; return pointer to end of cpu-specific text */ +{ + char *name=start; + char *s; + + if (s = skip_identifier(name)) { + /* Atari MadMac compatibility directives */ + if (*name == '.') /* ignore leading dot */ + name++; + + if (s-name==3 && !strnicmp(name,"dsp",3)) { + cpu_type = DSP; + eol(s); + return skip_line(s); + } + + else if (s-name==3 && !strnicmp(name,"gpu",3)) { + cpu_type = GPU; + eol(s); + return skip_line(s); + } + + else if (s-name==8 && !strnicmp(name,"regundef",8) || + s-name==9 && !strnicmp(name,"equrundef",9)) { + /* undefine a register symbol */ + s = skip(s); + if (name = parse_identifier(&s)) { + undef_regsym(name,0,RTYPE_R); + myfree(name); + eol(s); + return skip_line(s); + } + } + + else if (s-name==7 && !strnicmp(name,"ccundef",7)) { + /* undefine a condition code symbol */ + s = skip(s); + if (name = parse_identifier(&s)) { + undef_regsym(name,0,RTYPE_CC); + myfree(name); + eol(s); + return skip_line(s); + } + } + } + + return start; +} + + +int parse_cpu_label(char *labname,char **start) +/* parse cpu-specific directives following a label field, + return zero when no valid directive was recognized */ +{ + char *dir=*start; + char *s,*name; + hashdata data; + + if (*dir == '.') /* ignore leading dot */ + dir++; + + if (s = skip_identifier(dir)) { + + if (s-dir==6 && !strnicmp(dir,"regequ",6) || + s-dir==4 && !strnicmp(dir,"equr",4)) { + /* label REGEQU Rn || label EQUR Rn */ + int r; + + if ((r = parse_reg(&s)) >= 0) + new_regsym(0,0,labname,RTYPE_R,0,r); + else + cpu_error(3); /* register expected */ + eol(s); + *start = skip_line(s); + return 1; + } + + else if (s-dir==5 && !strnicmp(dir,"ccdef",5)) { + /* label CCDEF expr */ + expr *ccexp; + taddr val; + + if ((ccexp = parse_cc(&s)) != NULL) { + if (eval_expr(ccexp,&val,NULL,0)) + new_regsym(0,0,labname,RTYPE_CC,0,(int)val); + else + general_error(30); /* expression must be a constant */ + } + else + general_error(9); /* @@@ */ + eol(s); + *start = skip_line(s); + return 1; + } + } + + return 0; +} + + +operand *new_operand(void) +{ + operand *new = mymalloc(sizeof(*new)); + + new->type = NO_OP; + return new; +} + + +int jag_data_operand(int bits) +/* return data operand type for these number of bits */ +{ + if (bits & OPSZ_SWAP) + return DATAI_OP; + return bits==64 ? DATA64_OP : DATA_OP; +} + + +int parse_operand(char *p, int len, operand *op, int required) +{ + int reg; + + switch (required) { + case IMM0: + case IMM1: + case IMM1S: + case SIMM: + case IMMLW: + if (*p == '#') + p = skip(p+1); /* skip optional '#' */ + case REL: + case DATA_OP: + case DATAI_OP: + if (required == IMM1S) { + op->val = make_expr(SUB,number_expr(32),parse_expr(&p)); + required = IMM1; /* turn into IMM1 32-val for SHLQ */ + } + else + op->val = parse_expr(&p); + break; + + case DATA64_OP: + op->val = parse_expr_huge(&p); + break; + + case REG: /* Rn */ + op->reg = parse_reg(&p); + if (op->reg < 0) + return PO_NOMATCH; + break; + + case IREG: /* (Rn) */ + if (*p++ != '(') + return PO_NOMATCH; + op->reg = parse_reg(&p); + if (op->reg < 0) + return PO_NOMATCH; + if (*p != ')') + return PO_NOMATCH; + break; + + case IR14D: /* (R14+d) */ + case IR15D: /* (R15+d) */ + if (*p++ != '(') + return PO_NOMATCH; + reg = parse_reg(&p); + if ((required==IR14D && reg!=14) || (required==IR15D && reg!=15)) + return PO_NOMATCH; + if (*p++ != '+') + return PO_NOMATCH; + p = skip(p); + op->val = parse_expr(&p); + p = skip(p); + if (*p != ')') + return PO_NOMATCH; + break; + + case IR14R: /* (R14+Rn) */ + case IR15R: /* (R15+Rn) */ + if (*p++ != '(') + return PO_NOMATCH; + reg = parse_reg(&p); + if ((required==IR14R && reg!=14) || (required==IR15R && reg!=15)) + return PO_NOMATCH; + if (*p++ != '+') + return PO_NOMATCH; + op->reg = parse_reg(&p); + if (op->reg < 0) + return PO_NOMATCH; + if (*p != ')') + return PO_NOMATCH; + break; + + case CC: /* condition code: t, eq, ne, mi, pl, cc, cs, ... */ + op->val = parse_cc(&p); + break; + + case PC: /* PC register */ + if (toupper((unsigned char)*p) != 'P' || + toupper((unsigned char)*(p+1)) != 'C' || + ISIDCHAR(*(p+2))) + return PO_NOMATCH; + break; + + default: + return PO_NOMATCH; + } + + op->type = required; + return PO_MATCH; +} + + +static int32_t eval_oper(instruction *ip,operand *op,section *sec, + taddr pc,dblock *db) +{ + symbol *base = NULL; + int optype = op->type; + int btype; + taddr val,loval,hival,mask; + + switch (optype) { + case PC: + return 0; + + case REG: + case IREG: + case IR14R: + case IR15R: + return op->reg; + + case IMM0: + case IMM1: + case SIMM: + case IMMLW: + case IR14D: + case IR15D: + case REL: + case CC: + mask = 0x1f; + if (!eval_expr(op->val,&val,sec,pc)) + btype = find_base(op->val,&base,sec,pc); + + if (optype==IMM0 || optype==CC || optype==IMM1 || optype==SIMM) { + if (base != NULL) { + loval = -32; + hival = 32; + if (btype != BASE_ILLEGAL) { + if (db) { + add_extnreloc_masked(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS, + jag_big_endian?6:5,5,0,0x1f); + base = NULL; + } + } + } + else if (optype==IMM1) { + loval = 1; + hival = 32; + } + else if (optype==SIMM) { + loval = -16; + hival = 15; + } + else { + loval = 0; + hival = 31; + } + } + else if (optype==IR14D || optype==IR15D) { + if (base==NULL && val==0) { + /* Optimize (Rn+0) to (Rn). Assume that the "load/store (Rn+d)" + instructions follow directly after "load/store (Rn)". */ + ip->code -= optype==IR14D ? 1 : 2; + op->type = IREG; + op->reg = optype==IR14D ? 14 : 15; + return op->reg; + } + loval = 1; + hival = 32; + } + else if (optype==IMMLW) { + mask = ~0; + if (base != NULL) { + if (btype != BASE_ILLEGAL) { + if (db) { + /* two relocations for LSW first, then MSW */ + add_extnreloc_masked(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS, + 0,16,2,0xffff); + add_extnreloc_masked(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS, + 16,16,2,0xffff0000); + base = NULL; + } + } + } + } + else if (optype==REL) { + loval = -16; + hival = 15; + if ((base!=NULL && btype==BASE_OK && !is_pc_reloc(base,sec)) || + base==NULL) { + /* known label from same section or absolute label */ + val = (val - (pc + 2)) / 2; + } + else if (btype == BASE_OK) { + /* external label or from a different section (distance / 2) */ + add_extnreloc_masked(&db->relocs,base,val-2,REL_PC, + jag_big_endian?6:5,5,0,0x3e); + } + base = NULL; + } + else ierror(0); + + if (base != NULL) + general_error(38); /* bad or unhandled reloc: illegal relocation */ + + /* range check for this addressing mode */ + if (mask!=~0 && (valhival)) + cpu_error(1,(long)loval,(long)hival); + return val & mask; + + default: + ierror(0); + break; + } + + return 0; /* default */ +} + + +size_t instruction_size(instruction *ip, section *sec, taddr pc) +{ + return ip->code==OC_MOVEI ? 6 : 2; +} + + +dblock *eval_instruction(instruction *ip, section *sec, taddr pc) +{ + dblock *db = new_dblock(); + int32_t src=0,dst=0,extra; + int size = 2; + uint16_t inst; + + /* get source and destination argument, when present */ + if (ip->op[0]) + dst = eval_oper(ip,ip->op[0],sec,pc,db); + if (ip->op[1]) { + if (ip->code == OC_MOVEI) { + extra = dst; + size = 6; + } + else + src = dst; + dst = eval_oper(ip,ip->op[1],sec,pc,db); + } + else if (ip->code == OC_UNPACK) + src = 1; /* pack(src=0)/unpack(src=1) use the same opcode */ + + /* store and jump instructions need the second operand in the source field */ + if (mnemonics[ip->code].ext.flags & OPSWAP) { + extra = src; + src = dst; + dst = extra; + } + + /* allocate dblock data for instruction */ + db->size = size; + db->data = mymalloc(size); + + /* construct the instruction word out of opcode and source/dest. value */ + inst = (mnemonics[ip->code].ext.opcode & 63) << 10; + inst |= ((src&31) << 5) | (dst & 31); + + /* write instruction */ + if (jag_big_endian) { + db->data[0] = (inst >> 8) & 0xff; + db->data[1] = inst & 0xff; + } + else { + db->data[0] = inst & 0xff; + db->data[1] = (inst >> 8) & 0xff; + } + + /* extra words for MOVEI are always written in the order lo-word, hi-word */ + if (size == 6) + jagswap32(&db->data[2],extra); + + return db; +} + + +dblock *eval_data(operand *op, size_t bitsize, section *sec, taddr pc) +{ + dblock *db = new_dblock(); + taddr val; + + if (bitsize!=8 && bitsize!=16 && bitsize!=32 && bitsize!=64) + cpu_error(0,bitsize); /* data size not supported */ + + if (op->type!=DATA_OP && op->type!=DATA64_OP && op->type!=DATAI_OP) + ierror(0); + + db->size = bitsize >> 3; + db->data = mymalloc(db->size); + + if (op->type == DATA64_OP) { + thuge hval; + + if (!eval_expr_huge(op->val,&hval)) + general_error(59); /* cannot evaluate huge integer */ + huge_to_mem(jag_big_endian,db->data,db->size,hval); + } + else { + if (!eval_expr(op->val,&val,sec,pc)) { + symbol *base; + int btype; + + btype = find_base(op->val,&base,sec,pc); + if (base!=NULL && btype!=BASE_ILLEGAL) { + if (op->type == DATAI_OP) { + /* swapped: two relocations for LSW first, then MSW */ + add_extnreloc_masked(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS, + 0,16,0,0xffff); + add_extnreloc_masked(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS, + 16,16,0,0xffff0000); + } + else /* normal 8, 16, 32 bit relocation */ + add_extnreloc(&db->relocs,base,val, + btype==BASE_PCREL?REL_PC:REL_ABS,0,bitsize,0); + } + else if (btype != BASE_NONE) + general_error(38); /* illegal relocation */ + } + + switch (db->size) { + case 1: + db->data[0] = val & 0xff; + break; + case 2: + case 4: + if (op->type == DATAI_OP) + jagswap32(db->data,(int32_t)val); + else + setval(jag_big_endian,db->data,db->size,val); + break; + default: + ierror(0); + break; + } + } + + return db; +} + + +int cpu_available(int idx) +{ + return (mnemonics[idx].ext.flags & cpu_type) != 0; +} diff --git a/vasm-1/cpus/jagrisc/cpu.h b/vasm-1/cpus/jagrisc/cpu.h new file mode 100644 index 0000000..27d086e --- /dev/null +++ b/vasm-1/cpus/jagrisc/cpu.h @@ -0,0 +1,86 @@ +/* +** cpu.h Jaguar RISC cpu-description header-file +** (c) in 2014-2017 by Frank Wille +*/ + +extern int jag_big_endian; +#define BIGENDIAN (jag_big_endian) +#define LITTLEENDIAN (!jag_big_endian) +#define VASM_CPU_JAGRISC 1 + +/* maximum number of operands for one mnemonic */ +#define MAX_OPERANDS 2 + +/* maximum number of mnemonic-qualifiers per mnemonic */ +#define MAX_QUALIFIERS 0 + +/* data type to represent a target-address */ +typedef int32_t taddr; +typedef uint32_t utaddr; + +/* minimum instruction alignment */ +#define INST_ALIGN 2 + +/* default alignment for n-bit data */ +#define DATA_ALIGN(n) ((n<=8)?1:2) + +/* operand class for n-bit data definitions */ +int jag_data_operand(int); +#define DATA_OPERAND(n) jag_data_operand(n) + +/* returns true when instruction is valid for selected cpu */ +#define MNEMONIC_VALID(i) cpu_available(i) + +/* type to store each operand */ +typedef struct { + uint8_t type; + int8_t reg; + expr *val; +} operand; + +/* operand types */ +enum { + NO_OP=0, + DATA_OP, + DATA64_OP, + DATAI_OP, /* 32-bit with swapped halfwords */ + REG, /* register Rn */ + IMM0, /* 5-bit immediate expression (0-31) */ + IMM1, /* 5-bit immediate expression (1-32) */ + IMM1S, /* 5-bit immediate expression 32-(1-32) for SHLQ */ + SIMM, /* 5-bit signed immediate expression (-16 - 15) */ + IMMLW, /* 32-bit immediate expression in extra longword */ + IREG, /* register indirect (Rn) */ + IR14D, /* register R14 plus displacement indirect (R14+n) */ + IR15D, /* register R15 plus displacement indirect (R15+n) */ + IR14R, /* register R14 plus register Rn indirect (R14+Rn) */ + IR15R, /* register R15 plus register Rn indirect (R15+Rn) */ + CC, /* condition code, t, cc, cs, eq, ne, mi, pl, hi */ + REL, /* relative branch, PC + 2 + (-16..15) words */ + PC /* PC register */ +}; + +/* additional mnemonic data */ +typedef struct { + uint8_t opcode; + uint8_t flags; +} mnemonic_extension; + +/* Values defined for the 'flags' field of mnemonic_extension. */ +#define GPU 1 +#define DSP 2 +#define ANY GPU|DSP + +#define OPSWAP 128 /* swapped operands in instruction word encoding */ + +/* Register symbols */ +#define HAVE_REGSYMS +#define REGSYMHTSIZE 64 +#define RTYPE_R 0 /* R0-R31 */ +#define RTYPE_CC 1 /* condition codes (0-31) */ + +/* Prototypes */ +int cpu_available(int); + +int parse_cpu_label(char *,char **); +#define PARSE_CPU_LABEL(l,s) parse_cpu_label(l,s) diff --git a/vasm-1/cpus/jagrisc/cpu_errors.h b/vasm-1/cpus/jagrisc/cpu_errors.h new file mode 100644 index 0000000..68db758 --- /dev/null +++ b/vasm-1/cpus/jagrisc/cpu_errors.h @@ -0,0 +1,3 @@ + "data size %d not supported",ERROR, + "value from %ld to %ld required",ERROR, + "register expected",ERROR, diff --git a/vasm-1/cpus/jagrisc/opcodes.h b/vasm-1/cpus/jagrisc/opcodes.h new file mode 100644 index 0000000..0995abb --- /dev/null +++ b/vasm-1/cpus/jagrisc/opcodes.h @@ -0,0 +1,72 @@ + "abs", { REG }, { 22, ANY }, + "add", { REG, REG }, { 0, ANY }, + "addc", { REG, REG }, { 1, ANY }, + "addq", { IMM1, REG }, { 2, ANY }, + "addqmod", { IMM1, REG }, { 63, DSP }, + "addqt", { IMM1, REG }, { 3, ANY }, + "and", { REG, REG }, { 9, ANY }, + "bclr", { IMM0, REG }, { 15, ANY }, + "bset", { IMM0, REG }, { 14, ANY }, + "btst", { IMM0, REG }, { 13, ANY }, + "cmp", { REG, REG }, { 30, ANY }, + "cmpq", { SIMM, REG }, { 31, ANY }, + "div", { REG, REG }, { 21, ANY }, + "imacn", { REG, REG }, { 20, ANY }, + "imult", { REG, REG }, { 17, ANY }, + "imultn", { REG, REG }, { 18, ANY }, + "jr", { REL }, { 53, ANY|OPSWAP }, + "jr", { CC, REL }, { 53, ANY|OPSWAP }, + "jump", { IREG }, { 52, ANY|OPSWAP }, + "jump", { CC, IREG }, { 52, ANY|OPSWAP }, + "load", { IREG, REG }, { 41, ANY }, + "load", { IR14R, REG }, { 58, ANY }, + "load", { IR15R, REG }, { 59, ANY }, + "load", { IR14D, REG }, { 43, ANY }, + "load", { IR15D, REG }, { 44, ANY }, + "loadb", { IREG, REG }, { 39, ANY }, + "loadp", { IREG, REG }, { 42, GPU }, + "loadw", { IREG, REG }, { 40, ANY }, + "mirror", { REG, IREG }, { 48, DSP|OPSWAP }, + "mmult", { REG, REG }, { 54, ANY }, + "move", { REG, REG }, { 34, ANY }, + "move", { PC, REG }, { 51, ANY }, + "movefa", { REG, REG }, { 37, ANY }, + "movei", { IMMLW, REG }, { 38, ANY }, + "moveq", { IMM0, REG }, { 35, ANY }, + "moveta", { REG, REG }, { 36, ANY }, + "mtoi", { REG, REG }, { 55, ANY }, + "mult", { REG, REG }, { 16, ANY }, + "neg", { REG }, { 8, ANY }, + "nop", { NO_OP }, { 57, ANY }, + "normi", { REG, REG }, { 56, ANY }, + "not", { REG }, { 12, ANY }, + "or", { REG, REG }, { 10, ANY }, + "pack", { REG }, { 63, GPU }, + "resmac", { REG }, { 19, ANY }, + "ror", { REG, REG }, { 28, ANY }, + "rorq", { IMM1, REG }, { 29, ANY }, + "sat8", { REG }, { 32, GPU }, + "sat16", { REG }, { 33, GPU }, + "sat16s", { REG }, { 33, DSP }, + "sat24", { REG }, { 62, GPU }, + "sat32s", { REG }, { 42, DSP }, + "sh", { REG, REG }, { 23, ANY }, + "sha", { REG, REG }, { 26, ANY }, + "sharq", { IMM1, REG }, { 27, ANY }, + "shlq", { IMM1S, REG }, { 24, ANY }, + "shrq", { IMM1, REG }, { 25, ANY }, + "store", { REG, IREG }, { 47, ANY|OPSWAP }, + "store", { REG, IR14R }, { 60, ANY|OPSWAP }, + "store", { REG, IR15R }, { 61, ANY|OPSWAP }, + "store", { REG, IR14D }, { 49, ANY|OPSWAP }, + "store", { REG, IR15D }, { 50, ANY|OPSWAP }, + "storeb", { REG, IREG }, { 45, ANY|OPSWAP }, + "storep", { REG, IREG }, { 48, GPU|OPSWAP }, + "storew", { REG, IREG }, { 46, ANY|OPSWAP }, + "sub", { REG, REG }, { 4, ANY }, + "subc", { REG, REG }, { 5, ANY }, + "subq", { IMM1, REG }, { 6, ANY }, + "subqmod", { IMM1, REG }, { 32, DSP }, + "subqt", { IMM1, REG }, { 7, ANY }, + "unpack", { REG }, { 63, GPU }, + "xor", { REG, REG }, { 11, ANY }, diff --git a/vasm-1/cpus/m68k/cpu.c b/vasm-1/cpus/m68k/cpu.c new file mode 100644 index 0000000..09ac611 --- /dev/null +++ b/vasm-1/cpus/m68k/cpu.c @@ -0,0 +1,6003 @@ +/* +** cpu.c Motorola M68k, CPU32 and ColdFire cpu-description file +** (c) in 2002-2020 by Frank Wille +*/ + +#include +#include "vasm.h" +#include "error.h" + +#include "operands.h" + +struct specreg SpecRegs[] = { +#include "specregs.h" +}; +static int specreg_cnt = sizeof(SpecRegs)/sizeof(SpecRegs[0]); + +mnemonic mnemonics[] = { +#include "opcodes.h" +}; +int mnemonic_cnt = sizeof(mnemonics)/sizeof(mnemonics[0]); + +struct cpu_models models[] = { +#include "cpu_models.h" +}; +int model_cnt = sizeof(models)/sizeof(models[0]); + + +char *cpu_copyright="vasm M68k/CPU32/ColdFire cpu backend 2.3k (c) 2002-2020 Frank Wille"; +char *cpuname = "M68k"; +int bitsperbyte = 8; +int bytespertaddr = 4; + +int m68k_mid = 1; /* default a.out MID: 68000/68010 */ + +static uint32_t cpu_type = m68000; +static expr *baseexp[7]; /* basereg: expression loaded to reg. */ +static signed char sdreg = -1; /* current small-data base register */ +static signed char last_sdreg = -1; +static unsigned char phxass_compat = 0; +static unsigned char devpac_compat = 0; +static unsigned char gas = 0; /* true enables GNU-as mnemonics */ +static unsigned char sgs = 0; /* true enables & as immediate prefix */ +static unsigned char no_fpu = 0; /* true: FPU code/direct. disallowed */ +static unsigned char elfregs = 0; /* true: %Rn instead of Rn reg. names */ +static unsigned char fpu_id = 1; /* default coprocessor id for FPU */ +static unsigned char opt_gen = 1; /* generic optimizations (not Devpac) */ +static unsigned char opt_movem = 0; /* MOVEM Rn -> MOVE Rn */ +static unsigned char opt_pea = 0; /* MOVE.L #x,-(sp) -> PEA x */ +static unsigned char opt_clr = 0; /* MOVE #0, -> CLR */ +static unsigned char opt_st = 0; /* MOVE.B #-1, -> ST */ +static unsigned char opt_lsl = 0; /* LSL #1,Dn -> ADD Dn,Dn */ +static unsigned char opt_mul = 0; /* MULU/MULS #n,Dn -> LSL/ASL #n,Dn */ +static unsigned char opt_div = 0; /* DIVU/DIVS.L #n,Dn -> LSR/ASR #n,Dn */ +static unsigned char opt_fconst = 1; /* Fxxx.D #m,FPn -> Fxxx.S #m,FPn */ +static unsigned char opt_brajmp = 0; /* branch to different sect. into jump */ +static unsigned char opt_pc = 1; /*