Spin2

1679111218

Comments

  • Chip,
    While processing the skip routines I found that the length of the mask in some instances is > 22 although in fact because the skip values > 22 were all '0's so in fact it is OK.

    So my question:
    Should I just truncate the skip mask to 22 providing the values > 32 are all 0's ? This would be my choice :)
  • Cluso99 wrote: »
    Chip,
    While processing the skip routines I found that the length of the mask in some instances is > 22 although in fact because the skip values > 22 were all '0's so in fact it is OK.

    So my question:
    Should I just truncate the skip mask to 22 providing the values > 32 are all 0's ? This would be my choice :)

    The skip pattern only needs to involve the last '1' bit. Trailing '0's can be ignored.
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 01:40:02
    Chip,
    Here is the next version.
    Currently hardcoded - Input file is "C:/P2/Spin2/source.spin2" and output file is "source_execf.spin2"

    I've included your interpreter source (no tabs) with lines modified marked with *RR and *RRx. Comment lines marking start and end of blocks are not marked.

    I've allowed for a-z and A-Z but only in the first 52 columns. This means for >26 the spaces between columns need to be removed. Perhaps I should allow for 52 columns with spaces between ie check for 104 columns?

    See next post for questions regarding the lines beginning with the
    * label "callobj
    * label "una_iso" marked with my comment *RRx

    Here is a sample of the output file:
    '''~------------------------------------------------------------------------------
    ''hub_im          getnib  ad,pa,#0        'a b                                                    a: setup long[vbase][0..15]
    ''hub_ap          rfvar   ad              '| | c d e f g h i j k l m n o p q r s t                b: setup long[dbase][0..15]
    ''hub_pp          popa    ad              '| | | | | | | | | | | | | | | | | | | | u v w          c: setup byte[pbase + rfvar]
    ''                                        '                                                       d: setup byte[vbase + rfvar]
    ''                shl     x,#2            '| | | | | | | | | | | | | | | | | r s t | | w          e: setup byte[dbase + rfvar]
    ''                shl     x,#1            '| | | | | | | | | | | l m n | | | | | | | v |          f: setup byte[pbase + rfvar][pop index]
    ''                add     ad,x            '| | | | | f g h | | | l m n | | | r s t u v w          g: setup byte[vbase + rfvar][pop index]
    ''                shl     ad,#2           'a b | | | | | | | | | | | | | | | | | | | | |          h: setup byte[dbase + rfvar][pop index]
    ''                                        '                                                       i: setup word[pbase + rfvar]
    ''                add     ad,pbase        '| | c | | f | | i | | l | | o | | r | | | | |          j: setup word[vbase + rfvar]
    ''                add     ad,vbase        'a | | d | | g | | j | | m | | p | | s | | | |          k: setup word[dbase + rfvar]
    ''                add     ad,dbase        '| b | | e | | h | | k | | n | | q | | t | | |          l: setup word[pbase + rfvar][pop index]
    ''                                        '                                                       m: setup word[vbase + rfvar][pop index]
    ''hub_p           mov     ad,x            '| | | | | | | | | | | | | | | | | | | | | | | x y z    n: setup word[dbase + rfvar][pop index]
    ''                popa    x               '| | | | | f g h | | | l m n | | | r s t u v w x y z    o: setup long[pbase + rfvar]
    ''                                        '                                                       p: setup long[vbase + rfvar]
    ''                mov     rd,rd_long      'a b | | | | | | | | | | | | o p q r s t | | w | | z    q: setup long[dbase + rfvar]
    ''                mov     wr,wr_long      'a b | | | | | | | | | | | | o p q r s t | | w | | z    r: setup long[pbase + rfvar][pop index]
    ''                mov     sz,#31          'a b | | | | | | | | | | | | o p q r s t | | w | | z    s: setup long[vbase + rfvar][pop index]
    ''                                        '                                                       t: setup long[dbase + rfvar][pop index]
    ''                mov     rd,rd_byte      '| | c d e f g h | | | | | | | | | | | | u | | x | |    u: setup byte[pop base][pop index]
    ''                mov     wr,wr_byte      '| | c d e f g h | | | | | | | | | | | | u | | x | |    v: setup word[pop base][pop index]
    ''                mov     sz,#7           '| | c d e f g h | | | | | | | | | | | | u | | x | |    w: setup long[pop base][pop index]
    ''                                        '                                                       x: setup byte[pop address]
    ''                mov     rd,rd_word      '| | | | | | | | i j k l m n | | | | | | | v | | y |    y: setup word[pop address]
    ''                mov     wr,wr_word      '| | | | | | | | i j k l m n | | | | | | | v | | y |    z: setup long[pop address]
    ''                mov     sz,#15          '| | | | | | | | i j k l m n | | | | | | | v | | y |
    ''
    ''        _ret_   setq2   #$160           'a b c d e f g h i j k l m n o p q r s t u v w x y z    (next bytecode is variable operator)
    '''~~------------------------------------------------------------------------------
    hub_im_skip_a           = hub_im          | %0111111000111010111110 << 10  '
    hub_im_skip_b           = hub_im          | %0111111000110110111110 << 10  '
    hub_ap_skip_c           = hub_ap          |  %011100011111110111110 << 10  '
    hub_ap_skip_d           = hub_ap          |  %011100011111101111110 << 10  '
    hub_ap_skip_e           = hub_ap          |  %011100011111011111110 << 10  '
    hub_ap_skip_f           = hub_ap          |  %011100011101110101110 << 10  '
    hub_ap_skip_g           = hub_ap          |  %011100011101101101110 << 10  '
    hub_ap_skip_h           = hub_ap          |  %011100011101011101110 << 10  '
    hub_ap_skip_i           = hub_ap          |  %000011111111110111110 << 10  '
    hub_ap_skip_j           = hub_ap          |  %000011111111101111110 << 10  '
    hub_ap_skip_k           = hub_ap          |  %000011111111011111110 << 10  '
    hub_ap_skip_l           = hub_ap          |  %000011111101110100110 << 10  '
    hub_ap_skip_m           = hub_ap          |  %000011111101101100110 << 10  '
    hub_ap_skip_n           = hub_ap          |  %000011111101011100110 << 10  '
    hub_ap_skip_o           = hub_ap          |  %011111100011110111110 << 10  '
    hub_ap_skip_p           = hub_ap          |  %011111100011101111110 << 10  '
    hub_ap_skip_q           = hub_ap          |  %011111100011011111110 << 10  '
    hub_ap_skip_r           = hub_ap          |  %011111100001110101010 << 10  '
    hub_ap_skip_s           = hub_ap          |  %011111100001101101010 << 10  '
    hub_ap_skip_t           = hub_ap          |  %011111100001011101010 << 10  '
    hub_pp_skip_u           = hub_pp          |   %01110001110111110110 << 10  '
    hub_pp_skip_v           = hub_pp          |   %00001111110111110010 << 10  '
    hub_pp_skip_w           = hub_pp          |   %01111110000111110100 << 10  '
    hub_p_skip_x            = hub_p           |           %011100011100 << 10  '
    hub_p_skip_y            = hub_p           |           %000011111100 << 10  '
    hub_p_skip_z            = hub_p           |           %011111100000 << 10  '
    ''
    
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 03:45:16
    This causes an error because the columns contain vertical space(s). Not sure what to do here?
    '''~------------------------------------------------------------------------------
    ''callobj         rfvar   w               'a b c d         i j k l        get obj into w
    ''callsub         rfvar   v               'a b c d e f     i j k l m n    get sub into v
    ''                getptr  pb              'a b c d e f     i j k l m n    get updated ptr
    ''                jmp     #callh          'a b c d | f     i j k l m n    continue in hub
    ''                jmp     #callsubh       '        e                      continue in hub ('call sub' is optimized)
    ''callptr         jmp     #callptrh       '            g                  continue in hub
    ''
    ''
    ''callgo          rdfast  #0,x            'a b c d e f g h                return from hub, start new bytecode read
    ''                rfvar   x               'a b c d e f g h                get locals
    ''        _ret_   add     ptra,x          'a b c d e f g h                point stack past parameters+results+locals
    '''~~------------------------------------------------------------------------------
    ** mask invalid: callobj_skip_a          = callobj         |              %000  0000 << 10  '
    ** mask invalid: callobj_skip_b          = callobj         |              %000  0000 << 10  '
    ** mask invalid: callobj_skip_c          = callobj         |              %000  0000 << 10  '
    ** mask invalid: callobj_skip_d          = callobj         |              %000  0000 << 10  '
    ** mask invalid: callsub_skip_e          = callsub         |               %000 0100 << 10  '
    ** mask invalid: callsub_skip_f          = callsub         |               %000  000 << 10  '
    callptr_skip_g          = callptr         |                   %0000 << 10  '
    callgo_skip_h           = callgo          |                    %000 << 10  '
    callobj_skip_i          = callobj         |                   %0000 << 10  '
    callobj_skip_j          = callobj         |                   %0000 << 10  '
    callobj_skip_k          = callobj         |                   %0000 << 10  '
    callobj_skip_l          = callobj         |                   %0000 << 10  '
    callsub_skip_m          = callsub         |                    %000 << 10  '
    callsub_skip_n          = callsub         |                    %000 << 10  '
    ''
    

    The following needs a bit more explanation from you regarding the columns m & n.
    See following post.
    You'll note I shifted those m & n columns to the right because I reject from columns that do not contain the correct identifier. eg "x" in "m" column.
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 03:42:56
    Chip,
    OK, I can see what the m & n does...
    '''~------------------------------------------------------------------------------
    ''una_iso         mov     w,x             '                    m           a: !!                                *RRx
    ''una_psh         pusha   x               '                    | n         b: !                         push    *RRx
    ''                alti    rd              '                    m n         c: - (neg)                   rd      *RRx
    ''op_notb         test    x       wz      'a                   m n         d: ABS                       rd,!!   *RRx
    ''op_sqrt         qsqrt   x,#0            '|             h     x x         e: ENCOD                     SQRT    *RRx
    ''op_log          qlog    x               '|             | i   x x         f: DECOD                     LOG     *RRx
    ''op_exp          qexp    x               '|             | | j x x         g: ONES                      EXP     *RRx
    ''                muxz    x,_FFFFFFFF     'a             | | | x x         h: SQRT                      !!      *RRx
    ''op_not          not     x               '| b           | | | x x         i: LOG                       !       *RRx
    ''op_neg          neg     x               '| | c         | | | x x         j: EXP                       -       *RRx
    ''op_abs          abs     x               '| | | d       | | | x x                                      ABS     *RRx
    ''op_ncod         encod   x               '| | | | e     | | | x x                                      ENCOD   *RRx
    ''op_dcod         decod   x               '| | | | | f   | | | x x                                      DECOD   *RRx
    ''op_ones         ones    x               '| | | | | | g | | | x x                                      ONES    *RRx
    ''                getqx   x               '| | | | | | | h i j x x                                              *RRx
    ''                alti    wr              '| | | | | | | | | | m n                                      wr      *RRx
    ''                ret                     'a b c d e f g h i j m n         m: ?= var       (isolated)   wr,op   *RRx
    ''        _ret_   mov     x,w             '                    m |         n: ?= var       (push)       iso     *RRx
    ''        _ret_   zerox   x,sz            '                      n         x: use a..j                  push    *RRx
    '''~~------------------------------------------------------------------------------
    
    These are fine, and just a-j
    bc_lognot               long  op_notb   |        %01111111101110 << 10  '7A     !!exp           (NOT exp)
    bc_bitnot               long  op_not    |        %011111110_____ << 10  '7B     !exp
    bc_neg                  long  op_neg    |        %01111110______ << 10  '7C     -exp
    bc_abs                  long  op_abs    |        %0111110_______ << 10  '7D     ABS exp
    bc_encod                long  op_ncod   |        %011110________ << 10  '7E     ENCOD exp
    bc_decod                long  op_dcod   |        %01110_________ << 10  '7F     DECOD exp
    bc_ones                 long  op_ones   |        %0110__________ << 10  '80     ONES exp
    bc_sqrt                 long  op_sqrt   |        %0101111111110_ << 10  '81     SQRT exp
    bc_qlog                 long  op_log    |        %010111111110__ << 10  '82     QLOG exp
    bc_qexp                 long  op_exp    |        %01011111110___ << 10  '83     QEXP exp
    
    These take the value m=%%_000xxxxxxxxxxx0010 and replace the 'x' bits from a-j
    bc_lognot_write         long  una_iso   |    %000111111101110010 << 10  '17     !!= var         (isolated)
    bc_bitnot_write         long  una_iso   |    %000111111011110010 << 10  '18     != var          (isolated)
    bc_neg_write            long  una_iso   |    %000111110111110010 << 10  '19     -= var          (isolated)
    bc_abs_write            long  una_iso   |    %000111101111110010 << 10  '1A     ABS= var        (isolated)
    bc_encod_write          long  una_iso   |    %000111011111110010 << 10  '1B     ENCOD= var      (isolated)
    bc_decod_write          long  una_iso   |    %000110111111110010 << 10  '1C     DECOD= var      (isolated)
    bc_ones_write           long  una_iso   |    %000101111111110010 << 10  '1D     ONES= var       (isolated)
    bc_sqrt_write           long  una_iso   |    %000011111111100010 << 10  '1E     SQRT= var       (isolated)
    bc_qlog_write           long  una_iso   |    %000011111111010010 << 10  '1F     QLOG= var       (isolated)
    bc_qexp_write           long  una_iso   |    %000011111110110010 << 10  '20     QEXP= var       (isolated)
    
    And these take the value n=%%0100xxxxxxxxxxx000_ and replace the 'x' bits from a-j
    bc_lognot_write_push    long  una_psh   |    %010011111110111000 << 10  '3B     !!= var         (push)
    bc_bitnot_write_push    long  una_psh   |    %010011111101111000 << 10  '3C     != var          (push)
    bc_neg_write_push       long  una_psh   |    %010011111011111000 << 10  '3D     -= var          (push)
    bc_abs_write_push       long  una_psh   |    %010011110111111000 << 10  '3E     ABS= var        (push)
    bc_encod_write_push     long  una_psh   |    %010011101111111000 << 10  '3F     ENCOD= var      (push)
    bc_decod_write_push     long  una_psh   |    %010011011111111000 << 10  '40     DECOD= var      (push)
    bc_ones_write_push      long  una_psh   |    %010010111111111000 << 10  '41     ONES= var       (push)
    bc_sqrt_write_push      long  una_psh   |    %010001111111110000 << 10  '42     SQRT= var       (push)
    bc_qlog_write_push      long  una_psh   |    %010001111111101000 << 10  '43     QLOG= var       (push)
    bc_qexp_write_push      long  una_psh   |    %010001111111011000 << 10  '44     QEXP= var       (push)
    
    I can see what needs to happen. Just looking at how to express this in the source so that code can perform the exercise.
  • Good progress, Cluso99.

    Maybe 'x' is not a good indicator of 'use a..z', because it's part of the set. Perhaps '#' would be better to use for that case.
  • I think you're right to have 'start' and 'stop' indicators with dashes. I think you can safely ignore spaces within the group. They are not errant.
  • OK, I have the 'x' working. There were two complications...
    * obviously catering for the 'x'
    * catering for the case where the first instruction was an 'x' case but was in fact a different letter (m & n in the cases below)

    So here are those examples. Haven't done the combinations of m & n with a-j..
    '''~------------------------------------------------------------------------------
    ''una_iso         mov     w,x             '                    m           a: !!                                *RRx
    ''una_psh         pusha   x               '                    | n         b: !                         push    *RRx
    ''                alti    rd              '                    m n         c: - (neg)                   rd      *RRx
    ''op_notb         test    x       wz      'a                   m n         d: ABS                       rd,!!   *RRx
    ''op_sqrt         qsqrt   x,#0            '|             h     x x         e: ENCOD                     SQRT    *RRx
    ''op_log          qlog    x               '|             | i   x x         f: DECOD                     LOG     *RRx
    ''op_exp          qexp    x               '|             | | j x x         g: ONES                      EXP     *RRx
    ''                muxz    x,_FFFFFFFF     'a             | | | x x         h: SQRT                      !!      *RRx
    ''op_not          not     x               '| b           | | | x x         i: LOG                       !       *RRx
    ''op_neg          neg     x               '| | c         | | | x x         j: EXP                       -       *RRx
    ''op_abs          abs     x               '| | | d       | | | x x                                      ABS     *RRx
    ''op_ncod         encod   x               '| | | | e     | | | x x                                      ENCOD   *RRx
    ''op_dcod         decod   x               '| | | | | f   | | | x x                                      DECOD   *RRx
    ''op_ones         ones    x               '| | | | | | g | | | x x                                      ONES    *RRx
    ''                getqx   x               '| | | | | | | h i j x x                                              *RRx
    ''                alti    wr              '| | | | | | | | | | m n                                      wr      *RRx
    ''                ret                     'a b c d e f g h i j m n         m: ?= var       (isolated)   wr,op   *RRx
    ''        _ret_   mov     x,w             '                    m |         n: ?= var       (push)       iso     *RRx
    ''        _ret_   zerox   x,sz            '                      n         x: use a..j                  push    *RRx
    '''~~------------------------------------------------------------------------------
    op_notb_skip_a          = op_notb         |      %01111111101110___ << 10  '
    op_not_skip_b           = op_not          |      %011111110________ << 10  '
    op_neg_skip_c           = op_neg          |      %01111110_________ << 10  '
    op_abs_skip_d           = op_abs          |      %0111110__________ << 10  '
    op_ncod_skip_e          = op_ncod         |      %011110___________ << 10  '
    op_dcod_skip_f          = op_dcod         |      %01110____________ << 10  '
    op_ones_skip_g          = op_ones         |      %0110_____________ << 10  '
    op_sqrt_skip_h          = op_sqrt         |      %0101111111110____ << 10  '
    op_log_skip_i           = op_log          |      %010111111110_____ << 10  '
    op_exp_skip_j           = op_exp          |      %01011111110______ << 10  '
    una_iso_skip_m          = una_iso         |     %000xxxxxxxxxxx0010 << 10  '
    una_psh_skip_n          = una_psh         |    %0100xxxxxxxxxxx000_ << 10  '
    ''
    '''~------------------------------------------------------------------------------
    ''sha_mod         mov     w,x             'a b c d e       i j x x         a: >>                                *RRx
    ''rev_mod         not     w,x             '| | | | | f g h | | x x         b: <<                                *RRx
    ''                alti    rd              '| | | | | | | | | | m n         c: SAR                       rd      *RRx
    ''                popa    x               'a b c d e f g h i j m n         d: ROR                       rd,op   *RRx
    ''                rev     x               '| | | | | f | | | | x x         e: ROL                       REV     *RRx
    ''                shl     x,w             '| b | | | | g h | | x x         f: REV                       <<      *RRx
    ''                shr     x,w             'a | | | | f g | | | x x         g: ZEROX                     >>      *RRx
    ''                sar     x,w             '| | c | | | | h | | x x         h: SIGNX                     SAR     *RRx
    ''                ror     x,w             '| | | d | | | | | | x x         i: +                         ROR     *RRx
    ''                rol     x,w             '| | | | e | | | | | x x         j: -                         ROL     *RRx
    ''                add     x,w             '| | | | | | | | i | x x                                      +       *RRx
    ''                sub     x,w             '| | | | | | | | | j x x                                      -       *RRx
    ''                alti    wr              '| | | | | | | | | | m n                                      wr      *RRx
    ''                ret                     'a b c d e f g h i j m n         m: var ?= exp   (isolated)   wr,op   *RRx
    ''        _ret_   popa    x               '                    m |         n: var ?= exp   (push)       iso     *RRx
    ''        _ret_   zerox   x,sz            '                      n         x: use a..j                  push    *RRx
    '''~~------------------------------------------------------------------------------                             
    sha_mod_skip_a          = sha_mod         |         %01111110110110 << 10  '
    sha_mod_skip_b          = sha_mod         |         %01111111010110 << 10  '
    sha_mod_skip_c          = sha_mod         |         %01111101110110 << 10  '
    sha_mod_skip_d          = sha_mod         |         %01111011110110 << 10  '
    sha_mod_skip_e          = sha_mod         |         %01110111110110 << 10  '
    rev_mod_skip_f          = rev_mod         |         %0111111010010_ << 10  '
    rev_mod_skip_g          = rev_mod         |         %0111111001010_ << 10  '
    rev_mod_skip_h          = rev_mod         |         %0111110101010_ << 10  '
    sha_mod_skip_i          = sha_mod         |         %01101111110110 << 10  '
    sha_mod_skip_j          = sha_mod         |         %01011111110110 << 10  '
    sha_mod_skip_m          = sha_mod         |        %000xxxxxxxx00xx << 10  '
    sha_mod_skip_n          = sha_mod         |       %0100xxxxxxxx00xx << 10  '
    ''
    
  • There is this error case. I decided not to flag it, but to insert '?' where there were spaces for the tables.
    '''~------------------------------------------------------------------------------
    ''callobj         rfvar   w               'a b c d         i j k l        get obj into w
    ''callsub         rfvar   v               'a b c d e f     i j k l m n    get sub into v
    ''                getptr  pb              'a b c d e f     i j k l m n    get updated ptr
    ''                jmp     #callh          'a b c d | f     i j k l m n    continue in hub
    ''                jmp     #callsubh       '        e                      continue in hub ('call sub' is optimized)
    ''callptr         jmp     #callptrh       '            g                  continue in hub
    ''
    ''
    ''callgo          rdfast  #0,x            'a b c d e f g h                return from hub, start new bytecode read
    ''                rfvar   x               'a b c d e f g h                get locals
    ''        _ret_   add     ptra,x          'a b c d e f g h                point stack past parameters+results+locals
    '''~~------------------------------------------------------------------------------
    callobj_skip_a          = callobj         |              %000??0000 << 10  '
    callobj_skip_b          = callobj         |              %000??0000 << 10  '
    callobj_skip_c          = callobj         |              %000??0000 << 10  '
    callobj_skip_d          = callobj         |              %000??0000 << 10  '
    callsub_skip_e          = callsub         |              %000?0100_ << 10  '
    callsub_skip_f          = callsub         |              %000??000_ << 10  '
    callptr_skip_g          = callptr         |              %0000_____ << 10  '
    callgo_skip_h           = callgo          |              %000______ << 10  '
    callobj_skip_i          = callobj         |                   %0000 << 10  '
    callobj_skip_j          = callobj         |                   %0000 << 10  '
    callobj_skip_k          = callobj         |                   %0000 << 10  '
    callobj_skip_l          = callobj         |                   %0000 << 10  '
    callsub_skip_m          = callsub         |                   %000_ << 10  '
    callsub_skip_n          = callsub         |                   %000_ << 10  '
    ''
    
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 06:06:05
    Now, the other problem I found is where to terminate the columns. I fell foul of the 'x2' comment being within the table columns. No comment should be within the table columns but sometimes the program cannot determine that it has passed the end of the table columns. A simple <quote> after the columns on the first instruction line cures this. In most instances there are a number of comments lined up after the table rows and these can be detected as being the end of the table.

    This is the fix: place another comment char (') in the first table line after the tables. My program treats this as the end of line for the tables in this block. It's only necessary on the first instruction line of a block, and it can actually be any non-alpha character tho ' makes sense.
    '''~------------------------------------------------------------------------------
    ''inline_pasm     setq    #16-1                   'a              load local variables from hub into buff
    ''                rdlong  buff,dbase              'a
    ''                bith    v,#31                   'a              set flag to later restore local variables to hub
    ''
    ''                mov     ptrb,pb                 'a              get bytecode ptr into ptrb
    ''                skip    ##%11100100000111       'a          x2  begin inline_pasm skip pattern                *RR
    ''
    ''regexec_        skip    ##%1111000000           '| b        x2  begin REGEXEC skip pattern                    *RR
    ''regload_        mov     ptrb,x                  '| b c          get hubadr into ptrb
    ''
    ''                rdword  w,ptrb++                'a b c          read start register
    ''                rdword  y,ptrb++                'a b c          read length of pasm code, minus 1
    ''
    ''                setq    y                       'a b c          read in code
    ''                altd    w                       'a b c
    ''                rdlong  0,ptrb++                'a b c          altd causes ptrb++ to inc by 4, not by (y+1)*4
    ''
    ''        _ret_   popa    x                       '| | c          REGLOAD done, pop stack
    ''
    ''                shl     y,#2                    'a |            update bytecode ptr for inline_pasm
    ''                add     y,ptrb                  'a |
    ''
    ''call_pasm       mov     w,x                     '| |   d        get CALL address
    ''                popa    x                       '| b   d        pop stack
    ''
    ''                mov     y,pb                    '| b   d        save bytecode ptr
    ''                mov     z,ptra                  'a b   d        save ptra
    ''
    ''                call    w                       'a b   d        call pasm code (can use pa/pb/ptra/ptrb/stack, c/z=0)
    ''
    ''                testb   v,#31           wc      'a b   d        if inline_pasm, restore local variables to hub
    ''        if_c    setq    #16-1                   'a b   d
    ''        if_c    wrlong  buff,dbase              'a b   d
    ''
    ''                mov     ptra,z                  'a b   d        restore ptra
    ''        _ret_   mov     pb,y                    'a b   d        restore bytecode ptr
    '''~~------------------------------------------------------------------------------
    inline_pasm_skip_a      = inline_pasm     | %000_0000111001000001100000 << 10  '
    regexec__skip_b         = regexec_        | %00000000011110000000_____ << 10  '
    regload__skip_c         = regload_        |          %0000000______ << 10  '
    call_pasm_skip_d        = call_pasm       | %0000000000_______________ << 10  '
    _skip_x                 =                 |                 %00____ << 10  '
    ''
    
  • Latest code attached :)
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 13:24:51
    Here is a windows .exe for the program.
    It works from the command line where you can pass it the filename, or it will ask you for it. Default extension is ".spin2" if not supplied.
    The output file will be in the same directory with "_execf" appended to the filename before the "." extension. the source file will not be modified.

    BTW I've never built a python exe before tho it works fine on my W10 PC. I used pyinstaller to create the exe. There is a compiler for Linux and Mac available.
  • The practical way to handle ## cases, where two instructions are generated, would be for the user to just put an additional row of skip patterns in. That's pretty straightforward.
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 13:29:03
    cgracey wrote: »
    The practical way to handle ## cases, where two instructions are generated, would be for the user to just put an additional row of skip patterns in. That's pretty straightforward.
    Do you mean those m & n cases?
    Oh just realised what you meant. I didn’t notice what the x2 meant.

  • I mean where you saw the "x2", indicating there were TWO actual instructions, due to a 32-bit immediate value.
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 13:52:57
    Yes, just found it. Would be better to define a constant for those values and then just execute a single instruction as that would be faster and not use any extra longs.
    I just changed the source for the first m & n case and reran my program (as posted above - no changes). Here is the result - I left m & n in there
    '''~------------------------------------------------------------------------------
    ''una_iso         mov     w,x             '                    m p q r s t u v w x y                             a: !!                                *RRx
    ''una_psh         pusha   x               '                    | | | | | | | | | | | n P Q R S T U V W X Y       b: !                         push    *RRx
    ''                alti    rd              '                    m p q r s t u v w x y n P Q R S T U V W X Y       c: - (neg)                   rd      *RRx
    ''op_notb         test    x       wz      'a                   m p q r s t u v w x y n P Q R S T U V W X Y       d: ABS                       rd,!!   *RRx
    ''op_sqrt         qsqrt   x,#0            '|             h     x | | | | | | | w | | x | | | | | | | W | |       e: ENCOD                     SQRT    *RRx
    ''op_log          qlog    x               '|             | i   x | | | | | | | | x | x | | | | | | | | X |       f: DECOD                     LOG     *RRx
    ''op_exp          qexp    x               '|             | | j x | | | | | | | | | y x | | | | | | | | | Y       g: ONES                      EXP     *RRx
    ''                muxz    x,_FFFFFFFF     'a             | | | x p | | | | | | | | | x P | | | | | | | | |       h: SQRT                      !!      *RRx
    ''op_not          not     x               '| b           | | | x | q | | | | | | | | x | Q | | | | | | | |       i: LOG                       !       *RRx
    ''op_neg          neg     x               '| | c         | | | x | | r | | | | | | | x | | R | | | | | | |       j: EXP                       -       *RRx
    ''op_abs          abs     x               '| | | d       | | | x | | | s | | | | | | x | | | S | | | | | |                                    ABS     *RRx
    ''op_ncod         encod   x               '| | | | e     | | | x | | | | t | | | | | x | | | | T | | | | |                                    ENCOD   *RRx
    ''op_dcod         decod   x               '| | | | | f   | | | x | | | | | u | | | | x | | | | | U | | | |                                    DECOD   *RRx
    ''op_ones         ones    x               '| | | | | | g | | | x | | | | | | v | | | x | | | | | | V | | |                                    ONES    *RRx
    ''                getqx   x               '| | | | | | | h i j x | | | | | | | w x y x | | | | | | | W X Y                                            *RRx
    ''                alti    wr              '| | | | | | | | | | m p q r s t u v w x y n P Q R S T U V W X Y                                    wr      *RRx
    ''                ret                     'a b c d e f g h i j m p q r s t u v w x y n P Q R S T U V W X Y       m: ?= var       (isolated)   wr,op   *RRx
    ''        _ret_   mov     x,w             '                    m p q r s t u v w x y | | | | | | | | | | |       n: ?= var       (push)       iso     *RRx
    ''        _ret_   zerox   x,sz            '                                          n P Q R S T U V W X Y       x: use a..j                  push    *RRx
    '''~~------------------------------------------------------------------------------
    op_notb_skip_a          = op_notb         |      %01111111101110___ << 10  '
    op_not_skip_b           = op_not          |      %011111110________ << 10  '
    op_neg_skip_c           = op_neg          |      %01111110_________ << 10  '
    op_abs_skip_d           = op_abs          |      %0111110__________ << 10  '
    op_ncod_skip_e          = op_ncod         |      %011110___________ << 10  '
    op_dcod_skip_f          = op_dcod         |      %01110____________ << 10  '
    op_ones_skip_g          = op_ones         |      %0110_____________ << 10  '
    op_sqrt_skip_h          = op_sqrt         |      %0101111111110____ << 10  '
    op_log_skip_i           = op_log          |      %010111111110_____ << 10  '
    op_exp_skip_j           = op_exp          |      %01011111110______ << 10  '
    una_iso_skip_m          = una_iso         |     %000xxxxxxxxxxx0010 << 10  '
    una_iso_skip_p          = una_iso         |     %000111111101110010 << 10  '
    una_iso_skip_q          = una_iso         |     %000111111011110010 << 10  '
    una_iso_skip_r          = una_iso         |     %000111110111110010 << 10  '
    una_iso_skip_s          = una_iso         |     %000111101111110010 << 10  '
    una_iso_skip_t          = una_iso         |     %000111011111110010 << 10  '
    una_iso_skip_u          = una_iso         |     %000110111111110010 << 10  '
    una_iso_skip_v          = una_iso         |     %000101111111110010 << 10  '
    una_iso_skip_w          = una_iso         |     %000011111111100010 << 10  '
    una_iso_skip_x          = una_iso         |     %000011111111010010 << 10  '
    una_iso_skip_y          = una_iso         |     %000011111110110010 << 10  '
    una_psh_skip_n          = una_psh         |    %0100xxxxxxxxxxx000_ << 10  '
    una_psh_skip_P          = una_psh         |    %010011111110111000_ << 10  '
    una_psh_skip_Q          = una_psh         |    %010011111101111000_ << 10  '
    una_psh_skip_R          = una_psh         |    %010011111011111000_ << 10  '
    una_psh_skip_S          = una_psh         |    %010011110111111000_ << 10  '
    una_psh_skip_T          = una_psh         |    %010011101111111000_ << 10  '
    una_psh_skip_U          = una_psh         |    %010011011111111000_ << 10  '
    una_psh_skip_V          = una_psh         |    %010010111111111000_ << 10  '
    una_psh_skip_W          = una_psh         |    %010001111111110000_ << 10  '
    una_psh_skip_X          = una_psh         |    %010001111111101000_ << 10  '
    una_psh_skip_Y          = una_psh         |    %010001111111011000_ << 10  '
    ''
    
  • Chip,
    I think it would be best to generate new (ie separate) skip columns for those three x2 cases.

    I'm wondering how to generate the pattern without the <<10 and no label. Currently I will flag an error if a skip column starts without a label present.
    Any ideas?
  • Cluso99 wrote: »
    Yes, just found it. Would be better to define a constant for those values and then just execute a single instruction as that would be faster and not use any extra longs.
    I just changed the source for the first m & n case and reran my program (as posted above - no changes). Here is the result - I left m & n in there
    '''~------------------------------------------------------------------------------
    ''una_iso         mov     w,x             '                    m p q r s t u v w x y                             a: !!                                *RRx
    ''una_psh         pusha   x               '                    | | | | | | | | | | | n P Q R S T U V W X Y       b: !                         push    *RRx
    ''                alti    rd              '                    m p q r s t u v w x y n P Q R S T U V W X Y       c: - (neg)                   rd      *RRx
    ''op_notb         test    x       wz      'a                   m p q r s t u v w x y n P Q R S T U V W X Y       d: ABS                       rd,!!   *RRx
    ''op_sqrt         qsqrt   x,#0            '|             h     x | | | | | | | w | | x | | | | | | | W | |       e: ENCOD                     SQRT    *RRx
    ''op_log          qlog    x               '|             | i   x | | | | | | | | x | x | | | | | | | | X |       f: DECOD                     LOG     *RRx
    ''op_exp          qexp    x               '|             | | j x | | | | | | | | | y x | | | | | | | | | Y       g: ONES                      EXP     *RRx
    ''                muxz    x,_FFFFFFFF     'a             | | | x p | | | | | | | | | x P | | | | | | | | |       h: SQRT                      !!      *RRx
    ''op_not          not     x               '| b           | | | x | q | | | | | | | | x | Q | | | | | | | |       i: LOG                       !       *RRx
    ''op_neg          neg     x               '| | c         | | | x | | r | | | | | | | x | | R | | | | | | |       j: EXP                       -       *RRx
    ''op_abs          abs     x               '| | | d       | | | x | | | s | | | | | | x | | | S | | | | | |                                    ABS     *RRx
    ''op_ncod         encod   x               '| | | | e     | | | x | | | | t | | | | | x | | | | T | | | | |                                    ENCOD   *RRx
    ''op_dcod         decod   x               '| | | | | f   | | | x | | | | | u | | | | x | | | | | U | | | |                                    DECOD   *RRx
    ''op_ones         ones    x               '| | | | | | g | | | x | | | | | | v | | | x | | | | | | V | | |                                    ONES    *RRx
    ''                getqx   x               '| | | | | | | h i j x | | | | | | | w x y x | | | | | | | W X Y                                            *RRx
    ''                alti    wr              '| | | | | | | | | | m p q r s t u v w x y n P Q R S T U V W X Y                                    wr      *RRx
    ''                ret                     'a b c d e f g h i j m p q r s t u v w x y n P Q R S T U V W X Y       m: ?= var       (isolated)   wr,op   *RRx
    ''        _ret_   mov     x,w             '                    m p q r s t u v w x y | | | | | | | | | | |       n: ?= var       (push)       iso     *RRx
    ''        _ret_   zerox   x,sz            '                                          n P Q R S T U V W X Y       x: use a..j                  push    *RRx
    '''~~------------------------------------------------------------------------------
    op_notb_skip_a          = op_notb         |      %01111111101110___ << 10  '
    op_not_skip_b           = op_not          |      %011111110________ << 10  '
    op_neg_skip_c           = op_neg          |      %01111110_________ << 10  '
    op_abs_skip_d           = op_abs          |      %0111110__________ << 10  '
    op_ncod_skip_e          = op_ncod         |      %011110___________ << 10  '
    op_dcod_skip_f          = op_dcod         |      %01110____________ << 10  '
    op_ones_skip_g          = op_ones         |      %0110_____________ << 10  '
    op_sqrt_skip_h          = op_sqrt         |      %0101111111110____ << 10  '
    op_log_skip_i           = op_log          |      %010111111110_____ << 10  '
    op_exp_skip_j           = op_exp          |      %01011111110______ << 10  '
    una_iso_skip_m          = una_iso         |     %000xxxxxxxxxxx0010 << 10  '
    una_iso_skip_p          = una_iso         |     %000111111101110010 << 10  '
    una_iso_skip_q          = una_iso         |     %000111111011110010 << 10  '
    una_iso_skip_r          = una_iso         |     %000111110111110010 << 10  '
    una_iso_skip_s          = una_iso         |     %000111101111110010 << 10  '
    una_iso_skip_t          = una_iso         |     %000111011111110010 << 10  '
    una_iso_skip_u          = una_iso         |     %000110111111110010 << 10  '
    una_iso_skip_v          = una_iso         |     %000101111111110010 << 10  '
    una_iso_skip_w          = una_iso         |     %000011111111100010 << 10  '
    una_iso_skip_x          = una_iso         |     %000011111111010010 << 10  '
    una_iso_skip_y          = una_iso         |     %000011111110110010 << 10  '
    una_psh_skip_n          = una_psh         |    %0100xxxxxxxxxxx000_ << 10  '
    una_psh_skip_P          = una_psh         |    %010011111110111000_ << 10  '
    una_psh_skip_Q          = una_psh         |    %010011111101111000_ << 10  '
    una_psh_skip_R          = una_psh         |    %010011111011111000_ << 10  '
    una_psh_skip_S          = una_psh         |    %010011110111111000_ << 10  '
    una_psh_skip_T          = una_psh         |    %010011101111111000_ << 10  '
    una_psh_skip_U          = una_psh         |    %010011011111111000_ << 10  '
    una_psh_skip_V          = una_psh         |    %010010111111111000_ << 10  '
    una_psh_skip_W          = una_psh         |    %010001111111110000_ << 10  '
    una_psh_skip_X          = una_psh         |    %010001111111101000_ << 10  '
    una_psh_skip_Y          = una_psh         |    %010001111111011000_ << 10  '
    ''
    

    Because that code is in the hub and register space is at a premium, I used AUGS/AUGS.
  • Cluso99 wrote: »
    Chip,
    I think it would be best to generate new (ie separate) skip columns for those three x2 cases.

    I'm wondering how to generate the pattern without the <<10 and no label. Currently I will flag an error if a skip column starts without a label present.
    Any ideas?

    Something like this...
    regexec_	skip	##%1111000000		'| b	x2	begin REGEXEC skip pattern
    

    ...needs to be coded like this by the programmer...
    regexec_	skip	##%1111000000		'| b		begin REGEXEC skip pattern
    						'| b
    


    There is utility in making full 32-bit skip patterns. They are useful, too.

    No immediate ideas on your question, though.
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 21:20:06
    cgracey wrote: »
    Cluso99 wrote: »
    Chip,
    I think it would be best to generate new (ie separate) skip columns for those three x2 cases.

    I'm wondering how to generate the pattern without the <<10 and no label. Currently I will flag an error if a skip column starts without a label present.
    Any ideas?

    Something like this...
    regexec_	skip	##%1111000000		'| b	x2	begin REGEXEC skip pattern
    

    ...needs to be coded like this by the programmer...
    regexec_	skip	##%1111000000		'| b		begin REGEXEC skip pattern
    						'| b
    


    There is utility in making full 32-bit skip patterns. They are useful, too.

    No immediate ideas on your question, though.
    I wanted to perform as many error checks as possible.
    So I currently check for...
    * label - first column of line begins with alpha (“.” not valid for this)
    * instruction - any non-space character after a label, or if no label from 2nd position to the comment character
    * missing label for start of skip pattern
    * missing instruction (any non-blank data before comment) with valid skip pattern
    * valid skip pattern characters...
    * skip columns may start with space(s)
    * skip columns start with an alpha char a-z,A-Z and must have a label too
    * skip columns, once started, must contain either the alpha=“0”, |=“1”, space= end of pattern, (x allowed too), and optionally may have a label and must contain an instruction
    Generating the pattern...
    * leading pattern spaces are replaced with underscores in the pattern
    * the first valid alpha is used to locate the label, and is used...
    * generate a label for the pattern by adding “_skip_” plus the alpha char of the pattern
    * the label is used for the 10-bit address placeholder
    * maximum pattern length is 22 characters but if > 22 patterns above are checked for all “0”. An “_” is inserted between the 22 & 23 pattern to signify >22

    Now, to generate 32-bit skip masks, I think it would be better to have the header line beginning with “‘~~———“ to begin with “‘~~~——-“. This would signify that the generated bit pattern will be 32 bits without a 10-bit label. The generated label will be the same, as will all other checks.
    What do you think?

    Re the ##
    Currently your example would cause an error because there is no valid instruction in the added line.
    I think I need to check for the ## in the instruction field, and if found, insert a line with the same pattern. Do you agree?

    Re m & n masks using x
    I’ve changed your source to expand these columns. We have 64 pattern available. Do you think this is viable? And remove the m & n columns altogether, and thus the x usage?

  • cgraceycgracey Posts: 13,125
    edited 2020-01-25 - 22:03:41
    There could be two ## occurrences on a single line if both D and S are long immediates. That would mean replicating the skip bits 3x for that line.

    I kind of think, to keep things simple for your tool, key off and on like this, and just look at what is in the area below the pluses and above the minuses, using and verifying the + and - registrations:
    '
    ' Constants
    '					' + + + + + + + + + +
    const		pusha	x		' a b c d e f g h i j	a: constant -1..16
    		mov	x,pa		' a | | | | | | | | |	b: byte
    	_ret_	sub	x,#bc_con_n1-511' a | | | | | | | | |	c: byte!
    	_ret_	rfbyte	x		'   b | | | | | | | |	d: word
    		rfbyte	x		'     c | | | g h i j	e: word!
    	_ret_	rfword	x		'     | d | | | | | |	f: long
    		rfword	x		'     |   e | | | | |	g: byte + decod
    	_ret_	rflong	x		'     |   | f | | | |	h: byte + decod + not
    	_ret_	decod	x		'     |   |   g | | |	i: byte + bmask
    		decod	x		'     |   |     h | |	j: byte + bmask + not
    	_ret_	bmask	x		'     |   |     | i |
    		bmask	x		'     |   |     |   j
    	_ret_	not	x		'     c   e     h   j
    					' - - - - - - - - - -
    

    It's vital to track TAB characters along the way, too.
  • Cluso99Cluso99 Posts: 16,942
    edited 2020-01-25 - 23:51:42
    Here is what I've done for the ## case. It also includes an example of the bitmask size identified in the header.
    I'll fix for the case of two sets of ## in the same instruction (forgot about that)

    Perhaps we can use these for the start/end block as it makes it easier to detect?
    Can we keep the beginning of line '~nn (4 chars) for the start where nn=22 for a 22-bit mask with label, and '~32 for a 32-bit mask without label?
    I'll check for this plus the additional sequence ' + + + (7 chars).
    For the end sequence I'll check for '~ -- (4 chars) plus the sequence ' - - - (7 chars)
    I need the skip mask size in order to determine if a label is to be used and the mask <<10.
    '~22					' + + +
    '~32					' + + +
    '~--					' - - -
    

    I don't need to track tabs but if I find them I expand out 4 spaces. I only need to align the comment block.
    I output the source lines as comments before the skip definitions so you can see how they were generated. In the final version I'll provide a "-v" option to turn them on else they'll be off.

    The output file should be an include file in the original source as that way the source is never modified.

    Anyway, here is a sample of a 32-bit skip mask, and the ## in an instruction. Note the auto-inserted commented " not <augx placeholder> " line.
    '''~32----------------------------------------------------------------------------
    ''callh           nop                     'a b       f g h '      nop (instruction after branch cannot be skipped) *RRx2
    ''
    ''                add     w,x             '| b       | g |        add obj index
    ''
    ''                shl     w,#3            'a b       f g |        get obj offsets from w
    ''                add     w,pbase         'a b       f g |
    ''                setq    #2-1            'a b       f g |
    ''                rdlong  y,w             'a b       f g |        y = pbase offset, z = vbase offset
    ''
    ''                jmp     #makeptr        '| |       f g h        if method ptr, continue in hub
    ''
    ''                add     pbase,y         'a b                    add obj offsets into pbase/vbase
    ''                add     vbase,z         'a b  
    ''
    ''callsubh        pusha   x               'a | c                  if no call index, push x to save parameter
    ''
    ''calloffh        shl     v,#2            'a b c d e              get sub offset
    ''                add     v,pbase         'a b c d e
    ''                rdlong  v,v             'a b c d e              get bytecode params/results/offset
    ''
    ''                mov     x,v             'a b c d e              convert offset to branch address
    ''                add     x,pbase         'a b c d e
    ''
    ''                and     v,##$7FF00000   'a b c d e          x2  save params/results above return_address      *RR
    '' nop <**augx placeholder**>             'a b c d e          x2  save params/results above return_address      *RR
    ''                or      pb,v            'a b c d e
    ''
    ''                mov     dbase,dcall     'a b c d |              set dbase to dcall
    ''                mov     ptra,dbase      'a b c d |              point to stack base
    ''                rdlong  dcall,ptra[-1]  'a b c d |              read prior dcall from stack
    ''                wrlong  pb,ptra[-1]     'a b c d |              write params/results/return_address into stack
    ''
    ''                getbyte w,pb,#3         'a b c d e              point past parameters
    ''                shl     w,#2            'a b c d e
    ''                add     ptra,w          'a b c d e
    ''
    ''                getnib  w,pb,#5         'a b c d e              clear results
    ''                sub     w,#1    wc      'a b c d e
    ''        if_nc   setq    w               'a b c d e
    ''        if_nc   wrlong  #0,ptra++       'a b c d e              points past results
    ''
    ''                jmp     #callgo         'a b c d e              continue in cog
    '''~~------------------------------------------------------------------------------
    callh_skip_a            =   %000000000000000000000001000010
    callh_skip_b            =   %000000000000000000001001000000
    callsubh_skip_c         =   %000000000000000000000_________
    calloffh_skip_d         =   %00000000000000000000__________
    calloffh_skip_e         =   %00000000111100000000__________
    callh_skip_f            =                          %0000010
    callh_skip_g            =                          %0000000
    callh_skip_h            =                          %0111110
    ''
    
  • Was just thinking that it would be nice if you could change a "VAR" in a sub-object from a higher level object...

    For example, I'm playing around with a VGA driver and would be nice if could do:
    vga.boxcolor := $10
    

    To set the VAR section defined variable, "boxcolor", to the value $10

    Instead, I currently need to create a function like "SetBoxColor" in the VGA driver as a work around....
  • pedwardpedward Posts: 1,591
    edited 2020-01-30 - 18:43:34
    Ahh, public vs private...
    struct and class are equivalent in C++, only struct is public by default and class is private by default.
  • I've thought it would be good, too, to be able to access an object's VARs, to get around having to make methods. It could be made to work.
  • Syntax could look like this:
    CON	public	i = 2
    		j = 5
    		k = 11
    
    	private	m = 1
    		n = 2
    
    VAR	public	x,y,z
    
    	private	a,b,c
    

    The object-VAR sharing would just need some setup bytecodes:
    setup byte	obj.var
    setup byte	obj.var[index]
    setup byte	obj[index].var
    setup byte	obj[index].var[index]
    
    setup word	obj.var
    setup word	obj.var[index]
    setup word	obj[index].var
    setup word	obj[index].var[index]
    
    setup long	obj.var
    setup long	obj.var[index]
    setup long	obj[index].var
    setup long	obj[index].var[index]
    
    
    compile sequence for object-var setup:
    
    {push obj index}
    {push var index}
    setup bytecode
    rfvar obj
    rfvar var
    
  • Public / private syntax gets annoying. If it's not explicitly declared public or shared, it's private.

    KISS
  • cgraceycgracey Posts: 13,125
    edited 2020-01-30 - 19:37:18
    whicker wrote: »
    Public / private syntax gets annoying. If it's not explicitly declared public or shared, it's private.

    KISS

    I agree.
    CON	shared	i = 2,	j = 5,	k = 11
    		m = 1,	n = 2
    
    VAR	shared	x,y,x
    		a,b,c
    
  • Maybe something more subtle can be done:
    CON*	i = 2,	j = 5,	k = 11
    CON	m = 1,	n = 2
    
    VAR*	x,y,x
    VAR	a,b,c
    
    SUB* pulses(pin,count)
      repeat count
        pintoggle(pin)
        pintoggle(pin)
    
    SUB pulsesx2(pin,count)
      pulses(pin, count * 2)
    

    SUB replaces PUB/PRI, while * after the block type determines if it's public.
  • I think it is important to distinguish between a variable that can be read from the outside and one that can be both read and written from the outside. The lack of this distinction is one reason why C++ and Java programmers often use getter/setter methods instead of public instance variables. (The other reason is that a setter method can do more than just set the variable (usually to notify some other code about the changed variable))
Sign In or Register to comment.