Shop OBEX P1 Docs P2 Docs Learn Events
ZPU Emulator needs help with mul, div, and mod. — Parallax Forums

ZPU Emulator needs help with mul, div, and mod.

heaterheater Posts: 3,370
edited 2010-02-08 14:59 in Propeller 1
I know this has been asked before, and by me, but could someone point me to some nice small arithmetic routines in PASM
for use in the ZPU emulator?

ZPU requires:

Multiplication of two 32 bit twos complement integers with a 32 bit result.

Multiplication of two 16 bit unsigned numbers with a 32 bit result.

Division of a 32 bit twos complement integer by another with a 32 bit result.

Modulus, as above.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.

Comments

  • Cluso99Cluso99 Posts: 18,069
    edited 2010-02-08 08:42
  • heaterheater Posts: 3,370
    edited 2010-02-08 09:07
    Thank you Cluso. Problem is I don't understand a LONG of it [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-02-08 11:16
    Here is the mult/divide routine from my ClusoInterpreter. IIRC, most of this·is from Chip's original code.
    "a" holds the opcode (lower 5 bits as shown in the first block of code...·e.g. MPY=$F4=%10100)
    "x" and "y" are the two numbers to be multiplied (or divided) x * y or x / y, result is in "x" (pushed).

    So, if you use this routine with a set to...
    ·a = $F4 (multiply, return lower 32 bits),·= $F5 (multiply, return upper 32 bits), = $F6 (divide, return quotient 32 bits), = $F7 (divide, return remainder 32 bits)
    But, only set the lower 5 bits meaning $F4 --> $14, etc to save the first and a/#%11111 instruction.

    Hope this makes sense now cool.gif

      long i_bin +0 <<18 +math_F4 <<9 +math_bin '$F4 10100  MPY      1st * 2nd   b       *      *=   multiply, return lower half (signed)   
      long i_bin +0 <<18 +math_F4 <<9 +math_bin '$F5 10101  MPY_MSW  1st ** 2nd  b       **     **=  multiply, return upper half (signed)   
      long i_bin +0 <<18 +math_F4 <<9 +math_bin '$F6 10110  DIV      1st / 2nd   b       /      /=   divide, return quotient (signed)       
      long i_bin +0 <<18 +math_F4 <<9 +math_bin '$F7 10111  MOD      1st // 2nd  b       //     //=  divide, return remainder (signed)      
    

    '$F4..F7 = MUL/DIV lower/upper result
    math_F4                 and     a,#%11111               '<== and mask (need in a)
                            mov     t1,#0
                            mov     t2,#32                  'multiply/divide
                            abs     x,x             wc
                            muxc    a,#%01100
                            abs     y,y             wc,wz
            if_c            xor     a,#%00100
                            test    a,#%00010       wc      'set c if divide (DIV/MOD)
            if_c_and_nz     jmp     #mdiv                   'if divide and y=0, do multiply so result=0
                            shr     x,#1            wc      'multiply
    mmul    if_c            add     t1,y            wc
                            rcr     t1,#1           wc
                            rcr     x,#1            wc
                            djnz    t2,#mmul
                            test    a,#%00100       wz
            if_nz           neg     t1,t1
            if_nz           neg     x,x             wz
            if_nz           sub     t1,#1
                            test    a,#%00001       wz
            if_nz           mov     x,t1
                            jmp     #push
    mdiv                    shr     y,#1            wc,wz   'divide
                            rcr     t1,#1
            if_nz           djnz    t2,#mdiv
    mdiv2                   cmpsub  x,t1            wc
                            rcl     y,#1
                            shr     t1,#1
                            djnz    t2,#mdiv2
                            test    a,#%01000       wc
                            negc    x,x
                            test    a,#%00100       wc
                            test    a,#%00001       wz
            if_z            negc    x,y
                            jmp     #push
    
    







    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • heaterheater Posts: 3,370
    edited 2010-02-08 11:39
    Brilliant, that just drops straight in. At least the usage instruction make sense.

    With those in place the ZPU is eating 321 LONG in COG. Only three little ops to do and the main fetch execute loop.
    Looks like it will all fit in just fine.

    At the moment the dispatch table is 256 bytes in HUB. I can use byte entries in the table as all the opcode handler routines can fit in the first half of the COG nicely.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-02-08 11:44
  • heaterheater Posts: 3,370
    edited 2010-02-08 11:55
    By the way this first attempt is working with ZPU memory space in HUB.
    All the ZPU memory accesses have been localized to a few functions so moving to external RAM should be painless.

    Has anyone ever heard of an "Arithmetic Shift Left" ?

    The ZPU docs have defined one and it exists in their Java simulator. In fact they document this with the Java code:

    ASHIFTLEFT      43      arithmetic(signed) shift left.
    
    long shift;
    long valX;
    shift = ((long) popIntStack()) & INTMASK;
    valX = ((long) popIntStack()) & INTMASK;
    int t = (int) (valX << (shift & 0x3f));
    pushIntStack(t);
    
    



    What's the idea here ?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • BradCBradC Posts: 2,601
    edited 2010-02-08 12:09
    Looks like a standard shift left to me.
    Maybe they've done/named it to remain consistent with an ASR?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Life may be "too short", but it's the longest thing we ever do.
  • heaterheater Posts: 3,370
    edited 2010-02-08 12:17
    That's what I thought. Unless there is something going on with Java that I don't know about then that's what it will be in my PASM.

    It's an awfully long winded way of specifying it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • TonyDTonyD Posts: 210
    edited 2010-02-08 12:24
    I agree with BradC, looks like a standard shift left and they just named it ASL to remain consistent. If I remember correctly, Java uses << for both Arithmetic and Logical shift left as they are the same, but uses >>> for Logical Shift Right and >> for Arithmetic Shift Right.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Tony

    http://zuzebox.wordpress.com/
  • heaterheater Posts: 3,370
    edited 2010-02-08 13:28
    OK Just for completeness here is how they have defined all the shifts. The definition in the docs is just the same as the simulator Java code.

     LSHIFTRIGHT       42       unsigned shift right.
    
    long shift;
    long valX;
    int t;
    shift = ((long) popIntStack()) & INTMASK;
    valX = ((long) popIntStack()) & INTMASK;
    t = (int) (valX >> (shift & 0x3f));
    pushIntStack(t);
        
    ASHIFTLEFT     43     arithmetic(signed) shift left.
    
    long shift;
    long valX;
    shift = ((long) popIntStack()) & INTMASK;
    valX = ((long) popIntStack()) & INTMASK;
    int t = (int) (valX << (shift & 0x3f));
    pushIntStack(t);
        
    ASHIFTRIGHT     43     arithmetic(signed) shift left.
    
    long shift;
    int valX;
    shift = ((long) popIntStack()) & INTMASK;
    valX = popIntStack();
    int t = valX >> (shift & 0x3f);
    pushIntStack(t);
    
    
    



    So to my simple mind and zero understanding of any funky Java operator quirks this maps to PASM shifts as follows:

    LSHIFTRIGHT => SHR
    ASHIFTLEFT => SHL
    ASHIFTRIGHT => SAR

    ZyLin's naming of the SHL seems a little weird to me.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Cluso99Cluso99 Posts: 18,069
    edited 2010-02-08 13:48
    I agree. There are usually LSL, LSR, ASR.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
    · Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
  • heaterheater Posts: 3,370
    edited 2010-02-08 14:11
    I think I see where the confusion is coming from. In Suns Java tutorial pages we find this:
    Sun said...

    The signed left shift operator "<<" shifts a bit pattern to the left, and the signed right shift operator ">>" shifts a bit pattern to the right. The bit pattern is given by the left-hand operand, and the number of positions to shift by the right-hand operand. The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.

    Here they are talking about a "...signed left shift operator..." which basically does not make any sense to me as there is only one type of left shift and it does not care about the sign. Unless of course unless Java sign extends a signed 16 bit short when shifting it left and assigning to a 32 bit int. Hence "arithmetic shift left".



    I learned something new today. C is not guaranteed to use an arithmetic shift right for integers !

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-02-08 14:59
    Some computers have had both a signed shift left and an unsigned shift left. They produce the same numeric result. The difference is in the status bits from the operation, particularly if there's an overflow bit.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-02-08 14:59
    Some computers have had both a signed shift left and an unsigned shift left. They produce the same numeric result. The difference is in the status bits from the operation, particularly if there's an overflow bit.
Sign In or Register to comment.