P2 Tricks, Traps & Differences between P1 (Reference Material Only)

2»

Comments

  • ozpropdev wrote: »
    P2 does have a NOP opcode.
    0000 0000000 000 000000000 000000000        NOP
    

    Yes, all zeros is a special "NOP" case and is trapped by the silicon, rather than being a ROR instruction. If it wasn't trapped it would be a
    _RET_ ROR 0,0
    which would cause a _RET_ operation following the ROR 0,0 which would have no effect. Wouldn't want that.

    But in P1, anything with the CCCC=0 would become a NOP, so it was often used to hold a smaller variable, or convert an instruction to a NOP.
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • It's not that we don't have a NOP instruction, it's that we don't have a NOP condition.
  • evanhevanh Posts: 7,297
    edited 2019-02-14 - 14:28:12
    It really comes down to COGINIT requiring both a load address of zero and execution to start at zero. ORG has to be aligned to this. If you don't, you make a mess.

    That's why Pasm variables in all Obex programs are at the end.

    PS: You guys are messing up this topic with chatter!
    "... peers into the actual workings of a quantum jump for the first time. The results
    reveal a surprising finding that contradicts Danish physicist Niels Bohr's established view
    —the jumps are neither abrupt nor as random as previously thought."
  • msrobotsmsrobots Posts: 2,676
    edited 2019-02-14 - 16:23:53
    I like to reuse the top area in the COG where I normally place my startup code as res variables needed later and to store parameter I got from whoever started my COG.

    On the P2 one can do this very efficient.
    DAT
    cog     long  0
    PUB start(param1, param2, param3, param4)
       stop
       cog := cogstart(@entry, @param1) + 1
       
    PUB stop
       if cog
         cogstop(cog-1)
    
    DAT
    entry
            ORG0
    par1    rdlong par1, ptra++
    par2    rdlong par2, ptra++
    par3    rdlong par3, ptra++
    par4    rdlong par4, ptra++
    

    and now my parameter uses the same cog register used by the instruction needed to load the parameter

    you can't do that shorter,

    Enjoy!

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • Nice one.
  • Cluso99Cluso99 Posts: 15,084
    edited 2019-02-15 - 04:35:26
    Untested, but fairly sure this would work too, and you have 2 instructions to initialise something else.
    DAT
                    org     0
    entry           nop                             ' or something else
                    nop                             ' or something else
                    setq    #4-1
                    rdlong  entry,ptra
    
    Postedit: fixed setq value
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • It should be "setq #3", since the argument of setq in setq+rdlong is how many extra operations it should do, not the total number.
  • TIMEOUT

    Using the counter for timeouts

    Here is how to setup your own timeout
                    getct   timeout                         '\ set timeout value
                    add     timeout,          ##delay1s     '/
    
    and code to test if the timeout has been exceeded
                    getct   timenow                         '\ timeout ?
                    cmpm    timeout,          timenow   wc  '| c if timenow > timeout
            if_c    jmp     #timed_out                      '/ y: timed out          
    
    Note the use of the CMPM D,#/S {wc/wz/wcz} instruction!!!
    C = MSB of the result of D-S

    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • ozpropdevozpropdev Posts: 2,516
    edited 2019-02-22 - 09:20:41
    Timeouts can also be checked using the pollct instructions
                    getct   timeout                         '\ set timeout value
                    addct1     timeout,          ##delay1s     '/
    
    and code to test if the timeout has been exceeded
                    pollct1 wc
            if_c    jmp     #timed_out      
    
    Melbourne, Australia
  • Mark_TMark_T Posts: 1,981
    edited 2019-02-28 - 14:04:32
    One gotcha that regularly catches me out is that fastspin doesn't seem to detect duplicate labels as errors - is there a flag for more warnings?

    [ this is fixed in spin2gui release 1.3.9 and later ]
  • Mark_T wrote: »
    One gotcha that regularly catches me out is that fastspin doesn't seem to detect duplicate labels as errors - is there a flag for more warnings?

    That was a bug; I accidentally commented some error detection code out while debugging. It'll be fixed in the next version.
  • I stumbled about another issue, not bad but confusing.

    I can compile a sub-object without errors, but compiling the main object throws then errors in the sub object.

    Maybe you eliminate unused functions to early?

    Enjoy!

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • Okay, no more Fastspin bugs/discussions in this topic please. Pnut is okay because it has been frozen for ages.
    "... peers into the actual workings of a quantum jump for the first time. The results
    reveal a surprising finding that contradicts Danish physicist Niels Bohr's established view
    —the jumps are neither abrupt nor as random as previously thought."
  • Tip: use block reads/writes even for 2 longs:
                setq    #2-1
                rdlong  a, PTRA
                add     PTRA, #8
    
    ' is significantly faster than
    
                rdlong  a, PTRA++
                rdlong  a+1, PTRA++
    

    The issue is you only get synchronous access to the hub with block reads/writes, so the latter version has to wait
    7 cycles as it misses the boat on the second read. Block reads and writes run at one long per clock cycle, ie
    two per instruction time.
  • Here is a map of the special registers (P1 & P2 compared)
    ''  <------------- P1 ------------->  register  <--------------- P2 ---------------->     
    ''  ---------------------------------------------------------------------------------     
    ''  Boot Parameter              PAR   = $1F0 =  IJMP3  INT3  interrupt call   address     
    ''  System Counter              CNT   = $1F1 =  IRET3  INT3  interrupt return address     
    ''  Input  States     P31..P0   INA   = $1F2 =  IJMP2  INT2  interrupt call   address     
    ''  Input  States     P63..P32  INB   = $1F3 =  IRET2  INT2  interrupt return address     
    ''  Output States     P31..P0   OUTA  = $1F4 =  IJMP1  INT1  interrupt call   address     
    ''  Output States     P63..P32  OUTB  = $1F5 =  IRET1  INT1  interrupt return address     
    ''  Output Enables    P31..P0   DIRA  = $1F6 =  PA     CALLD/CALLPA/LOC                   
    ''  Output Enables    P63..P32  DIRB  = $1F7 =  PB     CALLD/CALLPB/LOC                   
    ''  Counter A Control           CTRA  = $1F8 =  PTRA   pointer A to hub RAM               
    ''  Counter B Control           CTRB  = $1F9 =  PTRB   pointer B to hub RAM               
    ''  Counter A Frequency         FRQA  = $1FA =  DIRA   P31..P0  Output Enables            
    ''  Counter B Frequency         FRQB  = $1FB =  DIRB   P63..P32 Output Enables            
    ''  Counter A Phase             PHSA  = $1FC =  OUTA   P31..P0  Output States             
    ''  Counter B Phase             PHSB  = $1FD =  OUTB   P63..P32 Output States             
    ''  Video Configuration         VCFG  = $1FE =  INA    P31..P0  Input  States  *          
    ''  Video Scale                 VSCL  = $1FF =  INB    P63..P32 Input  States  **         
    ''  ---------------------------------------------------------------------------------     
    
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • Here is a pointer to a discussion of using smart pin mode 00100 (pulse out): (click here)
    Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
  • A trap I ran across: the "altr" setting for writing to the result register (and presumably similar settings like "altd" and "alts") is destroyed by the "aug" prefix. So for example:
       altr 0, #A
       add B, #1
    
    puts B+1 into A, but:
       altr 0, #A
       add B, ##1
    
    puts B+1 into B (!). I thought of breaking the "add B, ##1" apart into an explicit aug+add and putting the altr between them, but since the altr uses an immediate that probably will fail too.

    There are work-arounds, but it's something to watch out for.
  • evanhevanh Posts: 7,297
    edited 2019-07-18 - 03:11:36
    A small defect with system clock setting got past the P2ES testing undetected. For clock config word, %0000_xxxE_DDDD_DDMM_MMMM_MMMM_PPPP_CCSS, if a PLL mode is configured with %PPPP = %1111 (_XDIVP = 1) there is a possibility of crashing if attempting to readjust the clock without knowing the exact config it is in.

    The solution for reliable operation into the future is to maintain a universal reserved hubRAM location containing a copy of the most recently issued config. That location is currently set as byte addresses $18 to $1b. Little-endian.

    Here is sample code for basic startup that includes the ability for a boot-loader to specify what config it has already set.
    CON
    	XTALFREQ	= 20_000_000                              'PLL stage 0: crystal frequency
    	XDIV		= 2                                       'PLL stage 1: crystal divider
    	XMUL		= 25                                      'PLL stage 2: crystal / div * mul
    	XDIVP		= 1                                       'PLL stage 3: crystal / div * mul / divp (1,2,4..30)
    
    	XOSC		= %10                             'OSC    ' %00=OFF, %01=OSC, %10=15pF, %11=30pF
    	XSEL		= %11                             'XI+PLL ' %00=rcfast(20+MHz), %01=rcslow(~20KHz), %10=XI(5ms), %11=XI+PLL(10ms)
    	XPPPP		= ((XDIVP>>1) + 15) & $F                  ' 1->15, 2->0, 4->1, 6->2...30->14
    	CLOCKFREQ	= XTALFREQ / XDIV * XMUL / XDIVP
    	SETFREQ		= 1<<24 + (XDIV-1)<<18 + (XMUL-1)<<8 + XPPPP<<4 + XOSC<<2
    	ENAFREQ		= SETFREQ + XSEL                          ' %0000_000e_dddddd_mmmmmmmmmm_pppp_cc_ss  ' enable oscillator
    
    
    DAT						'not Spin code
    ORGH  0						'loaded to hubram at address 0
    ORG						'longword addressing at 0
    		jmp     #_init
    		long	0,0,0
    '--------------------------------------------------------
    '***  Boot-loader can fill all four of the following  ***
    '--------------------------------------------------------
    spare1		long	0			'hubRAM addr $010 - compatible reserved for system variable
    clk_freq	long	CLOCKFREQ		'hubRAM addr $014 - sysclock frequency, integer frequency in hertz
    clk_mode	long	0			'hubRAM addr $018 - clock mode config word, used directly in HUBSET
    asyn_baud	long	BAUDRATE		'hubRAM addr $01c - comport baud rate, integer baud in hertz
    
    _init
    		andn	clk_mode, #%11		'clear the two select bits to force RCFAST selection
    		hubset	clk_mode		'switch to RCFAST using known prior mode
    		mov	clk_mode, ##SETFREQ	'replace old with new
    		hubset	clk_mode		'setup for new mode, still RCFAST
    		waitx	##20_000_000/100	'~10ms for crystal/PLL to come up to speed
    		hubset	##ENAFREQ		'engage
    		...
    		...
    

    EDIT: Ditched all the underscores in the constants to avoid Pnut symbol naming conflict
    EDIT2: (10-3-2019) Improved comments of system variables
    EDIT3: (24-6-2019) Link to original topic - https://forums.parallax.com/discussion/169838/p2-reset-possible-problem/p1
    EDIT4: (18-7-2019) Added ANDN masking for RCFAST clock selection - from Chip's Spin2 interpreter
    "... peers into the actual workings of a quantum jump for the first time. The results
    reveal a surprising finding that contradicts Danish physicist Niels Bohr's established view
    —the jumps are neither abrupt nor as random as previously thought."
  • Nice example, @evanh!

    But PNut throws the error "_CLKFREQ/_XINFREQ specified without _CLKMODE". So it looks like these three words may be reserved.
    garryj
  • clk_freq long _CLKFREQ 'hubRAM addr $014 - integer frequency in hertz

    should be _CLOCKFREQ
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • If using COGATN for synchronisation it's useful to know that the sender cog completes the COGATN instruction two sysclocks earlier than the WAITATN in the receiving cogs.
    "... peers into the actual workings of a quantum jump for the first time. The results
    reveal a surprising finding that contradicts Danish physicist Niels Bohr's established view
    —the jumps are neither abrupt nor as random as previously thought."
  • Here is a pointer to incmod: click here
    Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
  • I do not believe I am the only follower of this thread who had not seen (or perhaps forgot about) this description of all the P2 Instructions. click here
    Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
  • Getting the 64-bit CNT register
       GETCT A WC
       GETCT B
    

    Chip said...
    It's just for the next instruction (interrupts suspended to read the lower 32bits following reading the top 32bits, and no intervening instructions).
    I think the top 32 bits are two clocks ahead of the lower 32 bits. That's how it winds up time-aligned.

    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
Sign In or Register to comment.