Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* deco4004.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /*                                                                           */
  6. /* Dissector 4004                                                            */
  7. /*                                                                           */
  8. /*****************************************************************************/
  9.  
  10. #include "stdinc.h"
  11. #include <ctype.h>
  12.  
  13. #include "dasmdef.h"
  14. #include "cpulist.h"
  15. #include "codechunks.h"
  16. #include "invaddress.h"
  17. #include "strutil.h"
  18.  
  19. #include "deco4004.h"
  20.  
  21. typedef enum
  22. {
  23.   eUnknown,
  24.   eImplicit,
  25.   eFullAddr,
  26.   eFIM,
  27.   eOneReg,
  28.   eOneRReg,
  29.   eImm4,
  30.   eJumpCond,
  31.   eISZ
  32. } tAddrType;
  33.  
  34. typedef struct
  35. {
  36.   tAddrType Type;
  37.   Byte OpSize, NextAddresses;
  38.   const char *Memo;
  39. } tOpcodeList;
  40.  
  41. static unsigned nData;
  42.  
  43. static CPUVar CPU4004;
  44.  
  45. static const tOpcodeList OpcodeList[256] =
  46. {
  47.   /* 0x00 */ { eImplicit  , 0, 1, "nop"  },
  48.   /* 0x01 */ { eImplicit  , 0, 1, "hlt"  },
  49.   /* 0x02 */ { eImplicit  , 0, 0, "bbs"  },
  50.   /* 0x03 */ { eImplicit  , 0, 0, "lcr"  },
  51.   /* 0x04 */ { eImplicit  , 0, 0, "or4"  },
  52.   /* 0x05 */ { eImplicit  , 0, 0, "or5"  },
  53.   /* 0x06 */ { eImplicit  , 0, 1, "an6"  },
  54.   /* 0x07 */ { eImplicit  , 0, 1, "an7"  },
  55.   /* 0x08 */ { eImplicit  , 1, 1, "db0"  },
  56.   /* 0x09 */ { eImplicit  , 1, 1, "db1"  },
  57.   /* 0x0a */ { eImplicit  , 0, 0, "sb0"  },
  58.   /* 0x0b */ { eImplicit  , 0, 0, "sb1"  },
  59.   /* 0x0c */ { eImplicit  , 0, 1, "ein"  },
  60.   /* 0x0d */ { eImplicit  , 0, 1, "din"  },
  61.   /* 0x0e */ { eImplicit  , 0, 1, "rpm"  },
  62.   /* 0x0f */ { eUnknown   , 0, 0, NULL   },
  63.   /* 0x10 */ { eJumpCond  , 0, 3, "jcn"  },
  64.   /* 0x11 */ { eJumpCond  , 0, 3, "jcn"  },
  65.   /* 0x12 */ { eJumpCond  , 0, 3, "jcn"  },
  66.   /* 0x13 */ { eJumpCond  , 0, 3, "jcn"  },
  67.   /* 0x14 */ { eJumpCond  , 0, 3, "jcn"  },
  68.   /* 0x15 */ { eJumpCond  , 0, 3, "jcn"  },
  69.   /* 0x16 */ { eJumpCond  , 0, 3, "jcn"  },
  70.   /* 0x17 */ { eJumpCond  , 0, 3, "jcn"  },
  71.   /* 0x18 */ { eJumpCond  , 0, 3, "jcn"  },
  72.   /* 0x19 */ { eJumpCond  , 0, 3, "jcn"  },
  73.   /* 0x1a */ { eJumpCond  , 0, 3, "jcn"  },
  74.   /* 0x1b */ { eJumpCond  , 0, 3, "jcn"  },
  75.   /* 0x1c */ { eJumpCond  , 0, 3, "jcn"  },
  76.   /* 0x1d */ { eJumpCond  , 0, 3, "jcn"  },
  77.   /* 0x1e */ { eJumpCond  , 0, 3, "jcn"  },
  78.   /* 0x1f */ { eJumpCond  , 0, 3, "jcn"  },
  79.   /* 0x20 */ { eFIM       , 0, 1, "fim"  },
  80.   /* 0x21 */ { eOneRReg   , 0, 1, "src"  },
  81.   /* 0x22 */ { eFIM       , 0, 1, "fim"  },
  82.   /* 0x23 */ { eOneRReg   , 0, 1, "src"  },
  83.   /* 0x24 */ { eFIM       , 0, 1, "fim"  },
  84.   /* 0x25 */ { eOneRReg   , 0, 1, "src"  },
  85.   /* 0x26 */ { eFIM       , 0, 1, "fim"  },
  86.   /* 0x27 */ { eOneRReg   , 0, 1, "src"  },
  87.   /* 0x28 */ { eFIM       , 0, 1, "fim"  },
  88.   /* 0x29 */ { eOneRReg   , 0, 1, "src"  },
  89.   /* 0x2a */ { eFIM       , 0, 1, "fim"  },
  90.   /* 0x2b */ { eOneRReg   , 0, 1, "src"  },
  91.   /* 0x2c */ { eFIM       , 0, 1, "fim"  },
  92.   /* 0x2d */ { eOneRReg   , 0, 1, "src"  },
  93.   /* 0x2e */ { eFIM       , 0, 1, "fim"  },
  94.   /* 0x2f */ { eOneRReg   , 0, 1, "src"  },
  95.   /* 0x30 */ { eOneRReg   , 1, 1, "fin"  },
  96.   /* 0x31 */ { eOneRReg   , 1, 1, "jin"  },
  97.   /* 0x32 */ { eOneRReg   , 0, 1, "fin"  },
  98.   /* 0x33 */ { eOneRReg   , 0, 1, "jin"  },
  99.   /* 0x34 */ { eOneRReg   , 0, 1, "fin"  },
  100.   /* 0x35 */ { eOneRReg   , 0, 1, "jin"  },
  101.   /* 0x36 */ { eOneRReg   , 0, 1, "fin"  },
  102.   /* 0x37 */ { eOneRReg   , 0, 1, "jin"  },
  103.   /* 0x38 */ { eOneRReg   , 0, 1, "fin"  },
  104.   /* 0x39 */ { eOneRReg   , 0, 1, "jin"  },
  105.   /* 0x3a */ { eOneRReg   , 0, 1, "fin"  },
  106.   /* 0x3b */ { eOneRReg   , 0, 1, "jin"  },
  107.   /* 0x3c */ { eOneRReg   , 0, 1, "fin"  },
  108.   /* 0x3d */ { eOneRReg   , 0, 1, "jin"  },
  109.   /* 0x3e */ { eOneRReg   , 0, 1, "fin"  },
  110.   /* 0x3f */ { eOneRReg   , 0, 1, "jin"  },
  111.   /* 0x40 */ { eFullAddr  , 0, 2, "jun"  },
  112.   /* 0x41 */ { eFullAddr  , 0, 2, "jun"  },
  113.   /* 0x42 */ { eFullAddr  , 0, 2, "jun"  },
  114.   /* 0x43 */ { eFullAddr  , 0, 2, "jun"  },
  115.   /* 0x44 */ { eFullAddr  , 0, 2, "jun"  },
  116.   /* 0x45 */ { eFullAddr  , 0, 2, "jun"  },
  117.   /* 0x46 */ { eFullAddr  , 0, 2, "jun"  },
  118.   /* 0x47 */ { eFullAddr  , 0, 2, "jun"  },
  119.   /* 0x48 */ { eFullAddr  , 0, 2, "jun"  },
  120.   /* 0x49 */ { eFullAddr  , 0, 2, "jun"  },
  121.   /* 0x4a */ { eFullAddr  , 0, 2, "jun"  },
  122.   /* 0x4b */ { eFullAddr  , 0, 2, "jun"  },
  123.   /* 0x4c */ { eFullAddr  , 0, 2, "jun"  },
  124.   /* 0x4d */ { eFullAddr  , 0, 2, "jun"  },
  125.   /* 0x4e */ { eFullAddr  , 0, 2, "jun"  },
  126.   /* 0x4f */ { eFullAddr  , 0, 2, "jun"  },
  127.   /* 0x50 */ { eFullAddr  , 0, 3, "jms"  },
  128.   /* 0x51 */ { eFullAddr  , 0, 3, "jms"  },
  129.   /* 0x52 */ { eFullAddr  , 0, 3, "jms"  },
  130.   /* 0x53 */ { eFullAddr  , 0, 3, "jms"  },
  131.   /* 0x54 */ { eFullAddr  , 0, 3, "jms"  },
  132.   /* 0x55 */ { eFullAddr  , 0, 3, "jms"  },
  133.   /* 0x56 */ { eFullAddr  , 0, 3, "jms"  },
  134.   /* 0x57 */ { eFullAddr  , 0, 3, "jms"  },
  135.   /* 0x58 */ { eFullAddr  , 0, 3, "jms"  },
  136.   /* 0x59 */ { eFullAddr  , 0, 3, "jms"  },
  137.   /* 0x5a */ { eFullAddr  , 0, 3, "jms"  },
  138.   /* 0x5b */ { eFullAddr  , 0, 3, "jms"  },
  139.   /* 0x5c */ { eFullAddr  , 0, 3, "jms"  },
  140.   /* 0x5d */ { eFullAddr  , 0, 3, "jms"  },
  141.   /* 0x5e */ { eFullAddr  , 0, 3, "jms"  },
  142.   /* 0x5f */ { eFullAddr  , 0, 3, "jms"  },
  143.   /* 0x60 */ { eOneReg    , 0, 1, "inc"  },
  144.   /* 0x61 */ { eOneReg    , 0, 1, "inc"  },
  145.   /* 0x62 */ { eOneReg    , 0, 1, "inc"  },
  146.   /* 0x63 */ { eOneReg    , 0, 1, "inc"  },
  147.   /* 0x64 */ { eOneReg    , 0, 1, "inc"  },
  148.   /* 0x65 */ { eOneReg    , 0, 1, "inc"  },
  149.   /* 0x66 */ { eOneReg    , 0, 1, "inc"  },
  150.   /* 0x67 */ { eOneReg    , 0, 1, "inc"  },
  151.   /* 0x68 */ { eOneReg    , 0, 1, "inc"  },
  152.   /* 0x69 */ { eOneReg    , 0, 1, "inc"  },
  153.   /* 0x6a */ { eOneReg    , 0, 1, "inc"  },
  154.   /* 0x6b */ { eOneReg    , 0, 1, "inc"  },
  155.   /* 0x6c */ { eOneReg    , 0, 1, "inc"  },
  156.   /* 0x6d */ { eOneReg    , 0, 1, "inc"  },
  157.   /* 0x6e */ { eOneReg    , 0, 1, "inc"  },
  158.   /* 0x6f */ { eOneReg    , 0, 1, "inc"  },
  159.   /* 0x70 */ { eISZ       , 0, 3, "isz"  },
  160.   /* 0x71 */ { eISZ       , 0, 3, "isz"  },
  161.   /* 0x72 */ { eISZ       , 0, 3, "isz"  },
  162.   /* 0x73 */ { eISZ       , 0, 3, "isz"  },
  163.   /* 0x74 */ { eISZ       , 0, 3, "isz"  },
  164.   /* 0x75 */ { eISZ       , 0, 3, "isz"  },
  165.   /* 0x76 */ { eISZ       , 0, 3, "isz"  },
  166.   /* 0x77 */ { eISZ       , 0, 3, "isz"  },
  167.   /* 0x78 */ { eISZ       , 0, 3, "isz"  },
  168.   /* 0x79 */ { eISZ       , 0, 3, "isz"  },
  169.   /* 0x7a */ { eISZ       , 0, 3, "isz"  },
  170.   /* 0x7b */ { eISZ       , 0, 3, "isz"  },
  171.   /* 0x7c */ { eISZ       , 0, 3, "isz"  },
  172.   /* 0x7d */ { eISZ       , 0, 3, "isz"  },
  173.   /* 0x7e */ { eISZ       , 0, 3, "isz"  },
  174.   /* 0x7f */ { eISZ       , 0, 3, "isz"  },
  175.   /* 0x80 */ { eOneReg    , 0, 1, "add"  },
  176.   /* 0x81 */ { eOneReg    , 0, 1, "add"  },
  177.   /* 0x82 */ { eOneReg    , 0, 1, "add"  },
  178.   /* 0x83 */ { eOneReg    , 0, 1, "add"  },
  179.   /* 0x84 */ { eOneReg    , 0, 1, "add"  },
  180.   /* 0x85 */ { eOneReg    , 0, 1, "add"  },
  181.   /* 0x86 */ { eOneReg    , 0, 1, "add"  },
  182.   /* 0x87 */ { eOneReg    , 0, 1, "add"  },
  183.   /* 0x88 */ { eOneReg    , 0, 1, "add"  },
  184.   /* 0x89 */ { eOneReg    , 0, 1, "add"  },
  185.   /* 0x8a */ { eOneReg    , 0, 1, "add"  },
  186.   /* 0x8b */ { eOneReg    , 0, 1, "add"  },
  187.   /* 0x8c */ { eOneReg    , 0, 1, "add"  },
  188.   /* 0x8d */ { eOneReg    , 0, 1, "add"  },
  189.   /* 0x8e */ { eOneReg    , 0, 1, "add"  },
  190.   /* 0x8f */ { eOneReg    , 0, 1, "add"  },
  191.   /* 0x90 */ { eOneReg    , 0, 1, "sub"  },
  192.   /* 0x91 */ { eOneReg    , 0, 1, "sub"  },
  193.   /* 0x92 */ { eOneReg    , 0, 1, "sub"  },
  194.   /* 0x93 */ { eOneReg    , 0, 1, "sub"  },
  195.   /* 0x94 */ { eOneReg    , 0, 1, "sub"  },
  196.   /* 0x95 */ { eOneReg    , 0, 1, "sub"  },
  197.   /* 0x96 */ { eOneReg    , 0, 1, "sub"  },
  198.   /* 0x97 */ { eOneReg    , 0, 1, "sub"  },
  199.   /* 0x98 */ { eOneReg    , 0, 1, "sub"  },
  200.   /* 0x99 */ { eOneReg    , 0, 1, "sub"  },
  201.   /* 0x9a */ { eOneReg    , 0, 1, "sub"  },
  202.   /* 0x9b */ { eOneReg    , 0, 1, "sub"  },
  203.   /* 0x9c */ { eOneReg    , 0, 1, "sub"  },
  204.   /* 0x9d */ { eOneReg    , 0, 1, "sub"  },
  205.   /* 0x9e */ { eOneReg    , 0, 1, "sub"  },
  206.   /* 0x9f */ { eOneReg    , 0, 1, "sub"  },
  207.   /* 0xa0 */ { eOneReg    , 0, 1, "ld"   },
  208.   /* 0xa1 */ { eOneReg    , 0, 1, "ld"   },
  209.   /* 0xa2 */ { eOneReg    , 0, 1, "ld"   },
  210.   /* 0xa3 */ { eOneReg    , 0, 1, "ld"   },
  211.   /* 0xa4 */ { eOneReg    , 0, 1, "ld"   },
  212.   /* 0xa5 */ { eOneReg    , 0, 1, "ld"   },
  213.   /* 0xa6 */ { eOneReg    , 0, 1, "ld"   },
  214.   /* 0xa7 */ { eOneReg    , 0, 1, "ld"   },
  215.   /* 0xa8 */ { eOneReg    , 0, 1, "ld"   },
  216.   /* 0xa9 */ { eOneReg    , 0, 1, "ld"   },
  217.   /* 0xaa */ { eOneReg    , 0, 1, "ld"   },
  218.   /* 0xab */ { eOneReg    , 0, 1, "ld"   },
  219.   /* 0xac */ { eOneReg    , 0, 1, "ld"   },
  220.   /* 0xad */ { eOneReg    , 0, 1, "ld"   },
  221.   /* 0xae */ { eOneReg    , 0, 1, "ld"   },
  222.   /* 0xaf */ { eOneReg    , 0, 1, "ld"   },
  223.   /* 0xb0 */ { eOneReg    , 0, 1, "xch"  },
  224.   /* 0xb1 */ { eOneReg    , 0, 1, "xch"  },
  225.   /* 0xb2 */ { eOneReg    , 0, 1, "xch"  },
  226.   /* 0xb3 */ { eOneReg    , 0, 1, "xch"  },
  227.   /* 0xb4 */ { eOneReg    , 0, 1, "xch"  },
  228.   /* 0xb5 */ { eOneReg    , 0, 1, "xch"  },
  229.   /* 0xb6 */ { eOneReg    , 0, 1, "xch"  },
  230.   /* 0xb7 */ { eOneReg    , 0, 1, "xch"  },
  231.   /* 0xb8 */ { eOneReg    , 0, 1, "xch"  },
  232.   /* 0xb9 */ { eOneReg    , 0, 1, "xch"  },
  233.   /* 0xba */ { eOneReg    , 0, 1, "xch"  },
  234.   /* 0xbb */ { eOneReg    , 0, 1, "xch"  },
  235.   /* 0xbc */ { eOneReg    , 0, 1, "xch"  },
  236.   /* 0xbd */ { eOneReg    , 0, 1, "xch"  },
  237.   /* 0xbe */ { eOneReg    , 0, 1, "xch"  },
  238.   /* 0xbf */ { eOneReg    , 0, 1, "xch"  },
  239.   /* 0xc0 */ { eImm4      , 0, 0, "bbl"  },
  240.   /* 0xc1 */ { eImm4      , 0, 0, "bbl"  },
  241.   /* 0xc2 */ { eImm4      , 0, 0, "bbl"  },
  242.   /* 0xc3 */ { eImm4      , 0, 0, "bbl"  },
  243.   /* 0xc4 */ { eImm4      , 0, 0, "bbl"  },
  244.   /* 0xc5 */ { eImm4      , 0, 0, "bbl"  },
  245.   /* 0xc6 */ { eImm4      , 0, 0, "bbl"  },
  246.   /* 0xc7 */ { eImm4      , 0, 0, "bbl"  },
  247.   /* 0xc8 */ { eImm4      , 0, 0, "bbl"  },
  248.   /* 0xc9 */ { eImm4      , 0, 0, "bbl"  },
  249.   /* 0xca */ { eImm4      , 0, 0, "bbl"  },
  250.   /* 0xcb */ { eImm4      , 0, 0, "bbl"  },
  251.   /* 0xcc */ { eImm4      , 0, 0, "bbl"  },
  252.   /* 0xcd */ { eImm4      , 0, 0, "bbl"  },
  253.   /* 0xce */ { eImm4      , 1, 0, "bbl"  },
  254.   /* 0xcf */ { eImm4      , 0, 0, "bbl"  },
  255.   /* 0xd0 */ { eImm4      , 0, 1, "ldm"  },
  256.   /* 0xd1 */ { eImm4      , 0, 1, "ldm"  },
  257.   /* 0xd2 */ { eImm4      , 0, 1, "ldm"  },
  258.   /* 0xd3 */ { eImm4      , 0, 1, "ldm"  },
  259.   /* 0xd4 */ { eImm4      , 0, 1, "ldm"  },
  260.   /* 0xd5 */ { eImm4      , 0, 1, "ldm"  },
  261.   /* 0xd6 */ { eImm4      , 0, 1, "ldm"  },
  262.   /* 0xd7 */ { eImm4      , 0, 1, "ldm"  },
  263.   /* 0xd8 */ { eImm4      , 0, 1, "ldm"  },
  264.   /* 0xd9 */ { eImm4      , 0, 1, "ldm"  },
  265.   /* 0xda */ { eImm4      , 0, 1, "ldm"  },
  266.   /* 0xdb */ { eImm4      , 0, 1, "ldm"  },
  267.   /* 0xdc */ { eImm4      , 0, 1, "ldm"  },
  268.   /* 0xdd */ { eImm4      , 0, 1, "ldm"  },
  269.   /* 0xde */ { eImm4      , 0, 1, "ldm"  },
  270.   /* 0xdf */ { eImm4      , 0, 1, "ldm"  },
  271.   /* 0xe0 */ { eImplicit  , 0, 1, "wrm"  },
  272.   /* 0xe1 */ { eImplicit  , 0, 1, "wmp"  },
  273.   /* 0xe2 */ { eImplicit  , 0, 1, "wrr"  },
  274.   /* 0xe3 */ { eImplicit  , 0, 1, "wpm"  },
  275.   /* 0xe4 */ { eImplicit  , 0, 1, "wr0"  },
  276.   /* 0xe5 */ { eImplicit  , 0, 1, "wr1"  },
  277.   /* 0xe6 */ { eImplicit  , 0, 1, "wr2"  },
  278.   /* 0xe7 */ { eImplicit  , 0, 1, "wr3"  },
  279.   /* 0xe8 */ { eImplicit  , 0, 1, "sbm"  },
  280.   /* 0xe9 */ { eImplicit  , 0, 1, "rdm"  },
  281.   /* 0xea */ { eImplicit  , 0, 1, "rdr"  },
  282.   /* 0xeb */ { eImplicit  , 0, 1, "adm"  },
  283.   /* 0xec */ { eImplicit  , 0, 1, "rd0"  },
  284.   /* 0xed */ { eImplicit  , 0, 1, "rd1"  },
  285.   /* 0xee */ { eImplicit  , 1, 1, "rd2"  },
  286.   /* 0xef */ { eImplicit  , 1, 1, "rd3"  },
  287.   /* 0xf0 */ { eImplicit  , 0, 1, "clb"  },
  288.   /* 0xf1 */ { eImplicit  , 0, 1, "clc"  },
  289.   /* 0xf2 */ { eImplicit  , 0, 1, "iac"  },
  290.   /* 0xf3 */ { eImplicit  , 0, 1, "cmc"  },
  291.   /* 0xf4 */ { eImplicit  , 0, 1, "cma"  },
  292.   /* 0xf5 */ { eImplicit  , 0, 1, "ral"  },
  293.   /* 0xf6 */ { eImplicit  , 0, 1, "rar"  },
  294.   /* 0xf7 */ { eImplicit  , 0, 1, "tcc"  },
  295.   /* 0xf8 */ { eImplicit  , 0, 1, "dac"  },
  296.   /* 0xf9 */ { eImplicit  , 0, 1, "tcs"  },
  297.   /* 0xfa */ { eImplicit  , 0, 1, "stc"  },
  298.   /* 0xfb */ { eImplicit  , 0, 1, "daa"  },
  299.   /* 0xfc */ { eImplicit  , 0, 1, "kbp"  },
  300.   /* 0xfd */ { eImplicit  , 0, 1, "dcl"  },
  301.   /* 0xfe */ { eUnknown   , 1, 1, NULL   },
  302.   /* 0xff */ { eUnknown   , 1, 1, NULL   },
  303. };
  304.  
  305. static const tOpcodeList DummyOpcode = { eUnknown   , 0, 0, NULL   };
  306.  
  307. static void IntelHexString(char *pBuf, size_t BufSize, Word Num, int Digits)
  308. {
  309.   HexString(pBuf, BufSize, Num, Digits);
  310.   if (!as_isdigit(*pBuf))
  311.     strmaxprep(pBuf, "0", BufSize);
  312.   strmaxcat(pBuf, "h", BufSize);
  313. }
  314.  
  315. static Boolean RetrieveData(LargeWord Address, Byte *pBuffer, unsigned Count)
  316. {
  317.   LargeWord Trans;
  318.  
  319.   while (Count > 0)
  320.   {
  321.     Trans = 0x10000 - Address;
  322.     if (Count < Trans)
  323.       Trans = Count;
  324.     if (!RetrieveCodeFromChunkList(&CodeChunks, Address, pBuffer, Trans))
  325.     {
  326.       char NumString[50];
  327.  
  328.       HexString(NumString, sizeof(NumString), Address, 1);
  329.       fprintf(stderr, "cannot retrieve instruction arg @ 0x%s\n", NumString);
  330.       return FALSE;
  331.     }
  332.     pBuffer += Trans;
  333.     Count -= Trans;
  334.     Address = (Address + Trans) & 0xffff;
  335.     nData += Trans;
  336.   }
  337.   return TRUE;
  338. }
  339.  
  340. static const char *MakeSymbolic(Word Address, int AddrLen, const char *pSymbolPrefix, char *pBuffer, int BufferSize)
  341. {
  342.   const char *pResult;
  343.  
  344.   if ((pResult = LookupInvSymbol(Address)))
  345.     return pResult;
  346.  
  347.   HexString(pBuffer, BufferSize, Address, AddrLen << 1);
  348.   if (!pSymbolPrefix)
  349.   {
  350.     if (!isdigit(*pBuffer))
  351.     {
  352.       strmaxprep(pBuffer, "0", BufferSize);
  353.       strmaxcat(pBuffer, "h", BufferSize);
  354.     }
  355.     return pBuffer;
  356.   }
  357.  
  358.   strmaxprep(pBuffer, pSymbolPrefix, BufferSize);
  359.   AddInvSymbol(pBuffer, Address);
  360.   return pBuffer;
  361. }
  362.  
  363. static void Disassemble_4004(LargeWord Address, tDisassInfo *pInfo, Boolean AsData, int DataSize)
  364. {
  365.   Byte Opcode, Data[10];
  366.   const tOpcodeList *pOpcode;
  367.   char NumBuf[60], NumBuf2[60];
  368.   const char *pOp;
  369.   Word OpAddr = 0;
  370.  
  371.   pInfo->CodeLen = 0;
  372.   pInfo->NextAddressCount = 0;
  373.   pInfo->SrcLine[0] = '\0';
  374.   pInfo->pRemark = NULL;
  375.  
  376.   if (!RetrieveData(Address, &Opcode, 1))
  377.     return;
  378.   nData = 1;
  379.   (void)DataSize;
  380.  
  381.   pOpcode = AsData ? &DummyOpcode : OpcodeList + Opcode;
  382.   switch (pOpcode->Type)
  383.   {
  384.     case eImplicit:
  385.       pInfo->CodeLen = 1;
  386.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s", pOpcode->Memo);
  387.       break;
  388.     case eFullAddr:
  389.       if (!RetrieveData(Address + 1, Data, 1))
  390.         return;
  391.       pInfo->CodeLen = 2;
  392.       OpAddr = (((Word)Opcode & 0x0f) << 8) | Data[0];
  393.       pOp = MakeSymbolic(OpAddr, 2, strcmp(pOpcode->Memo, "jun") ? "lab_" : "sub_", NumBuf, sizeof(NumBuf));
  394.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s\t%s", pOpcode->Memo, pOp);
  395.       break;
  396.     case eJumpCond:
  397.       if (!RetrieveData(Address + 1, Data, 1))
  398.         return;
  399.       pInfo->CodeLen = 2;
  400.       OpAddr = ((Address + 2) & 0x0f00) | Data[0];
  401.       pOp = MakeSymbolic(OpAddr, 2, "lab_", NumBuf, sizeof(NumBuf));
  402.       NumBuf2[0] = '\0';
  403.       if (Opcode & 0x01)
  404.         strmaxcat(NumBuf2, "t", sizeof(NumBuf2));
  405.       if (Opcode & 0x02)
  406.         strmaxcat(NumBuf2, "c", sizeof(NumBuf2));
  407.       if (Opcode & 0x04)
  408.         strmaxcat(NumBuf2, "z", sizeof(NumBuf2));
  409.       if (Opcode & 0x08)
  410.         strmaxcat(NumBuf2, "n", sizeof(NumBuf2));
  411.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s\t%s,%s",
  412.                   pOpcode->Memo, NumBuf2, pOp);
  413.       break;
  414.     case eISZ:
  415.       if (!RetrieveData(Address + 1, Data, 1))
  416.         return;
  417.       pInfo->CodeLen = 2;
  418.       OpAddr = ((Address + 2) & 0x0f00) | Data[0];
  419.       pOp = MakeSymbolic(OpAddr, 2, "lab_", NumBuf, sizeof(NumBuf));
  420.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s\tr%u,%s",
  421.                   pOpcode->Memo, Opcode & 15, pOp);
  422.       break;
  423.     case eFIM:
  424.       if (!RetrieveData(Address + 1, Data, 1))
  425.         return;
  426.       pInfo->CodeLen = 2;
  427.       IntelHexString(NumBuf, sizeof(NumBuf), Data[0], 2);
  428.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s\tr%up,%s",
  429.                   pOpcode->Memo, (Opcode & 15) >> 1, NumBuf);
  430.       break;
  431.     case eOneReg:
  432.       pInfo->CodeLen = 1;
  433.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s\tr%u",
  434.                   pOpcode->Memo, Opcode & 15);
  435.       break;
  436.     case eOneRReg:
  437.       pInfo->CodeLen = 1;
  438.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s\tr%up",
  439.                   pOpcode->Memo, (Opcode & 15) >> 1);
  440.       break;
  441.     case eImm4:
  442.       pInfo->CodeLen = 1;
  443.       IntelHexString(NumBuf, sizeof(NumBuf), Opcode & 0x0f, 1);
  444.       as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "%s\t%s",
  445.                   pOpcode->Memo, NumBuf);
  446.       break;
  447.     default:
  448.       if (DataSize < 0)
  449.         DataSize = 1;
  450.       if (!RetrieveData(Address + 1, Data, DataSize - 1))
  451.         return;
  452.       HexString(NumBuf, sizeof(NumBuf), Opcode, 2);
  453.       HexString(NumBuf2, sizeof(NumBuf2), Address, 0);
  454.       if (!AsData)
  455.         fprintf(stderr, "unknown opcode 0x%s @ 0x%s\n", NumBuf, NumBuf2);
  456.       switch (DataSize)
  457.       {
  458.         case 2:
  459.           OpAddr = (((Word)Opcode) << 8) | Data[0];
  460.           pOp = MakeSymbolic(OpAddr, 2, NULL, NumBuf, sizeof(NumBuf));
  461.           as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "dw\t%s", pOp);
  462.           pInfo->CodeLen = 2;
  463.           break;
  464.         default:
  465.           pInfo->CodeLen = 1;
  466.           IntelHexString(NumBuf, sizeof(NumBuf), Opcode, 2);
  467.           as_snprintf(pInfo->SrcLine, sizeof(pInfo->SrcLine), "db\t%s", NumBuf);
  468.       }
  469.   }
  470.  
  471.   if (pOpcode->NextAddresses & 2)
  472.     pInfo->NextAddresses[pInfo->NextAddressCount++] = OpAddr;
  473.   if (pOpcode->NextAddresses & 1)
  474.     pInfo->NextAddresses[pInfo->NextAddressCount++] = (Address + pInfo->CodeLen) % 0xfff;
  475.  
  476.   if (nData != pInfo->CodeLen)
  477.     as_snprcatf(pInfo->SrcLine, sizeof(pInfo->SrcLine), " ; ouch %u != %u", nData, pInfo->CodeLen);
  478. }
  479.  
  480. static void SwitchTo_4004(void)
  481. {
  482.   Disassemble = Disassemble_4004;
  483. }
  484.  
  485. void deco4004_init(void)
  486. {
  487.   CPU4004 = AddCPU("4004", SwitchTo_4004);
  488. }
  489.