don't click here

Conditions in M68K

Discussion in 'Technical Discussion' started by saxman, May 26, 2008.

  1. saxman

    saxman

    Oldbie Tech Member
    What I wanna know is how the conditions work. That BNE (branch if not equal)... what are we comparing, and what are we comparing it to? There's no CMP or TST instructions. I've looked everywhere and can't find an explanation for this.
     
  2. Tweaker

    Tweaker

    Banned
    12,387
    2
    0
    Certain instructions (and, sub, and some others I can't think of) test the Z-flag when executed, essentially doubling as a tst (which checks for zero). You can do a conditional branch immediately after to save a few cycles. What that's doing is, after the AND instruction, branching if the result is NOT zero (hence the bne). It took me a while to figure out you could do this, too—I believe it was drx who told me about it. If you're optimizing for speed in the strictest sense of the word, then such a thing is important to keep in mind.

    On a side note, we have an
    Code (ASM):
    1.  tag which will syntax-highlight and preserve tabbing for M68k code, which I think you'll find much better to use than [quote]. :(
     
  3. saxman

    saxman

    Oldbie Tech Member
    Code (ASM):
    1.     cmpi.b  #$1E,anim_frame(a0)
    2.     bcs.s   Obj01_MdNormal
    What about that -- it branches if the carry bit is set. I'm confused as to what the carry bit has anything to do with the CMPI instruction. What is this portion actually doing in English?
     
  4. FraGag

    FraGag

    Tech Member
    Look at this wiki page: SCHG:68000 Instruction Set. At the bottom, the condition codes are described, with relational operators to help. So according to this, CS means "less than" (unsigned comparison).
     
  5. Tweaker

    Tweaker

    Banned
    12,387
    2
    0
    I'm blind—I used that page to look up the name of the Z-flag (wasn't sure to refer to bit or flag, so I just said flag =P) and I never noticed the headers for those conditional matchups. I think I'll convert that section into a proper table so it's easier to work out.
     
  6. saxman

    saxman

    Oldbie Tech Member
    You're right, I didn't realize the conditional match-ups there either. But this works.

    Okay another question... I know a0 generally points to the object we're currently dealing with, but what address is stored in a1? Reason I'm asking is there's this instance:

    Code (ASM):
    1. add.w   x_pos(a0),d1
    2. sub.w   x_pos(a1),d1
     
  7. Tweaker

    Tweaker

    Banned
    12,387
    2
    0
    I believe that, when dealing with Sonic, a1 is the address of the object that he's currently standing on. Correct me if I'm wrong, though; it may be Tails instead.
     
  8. FraGag

    FraGag

    Tech Member
    If you want to be 100% sure, backtrack the code until you see a lea something,a1. Inside an object's code, a1 should be explicitly initialized with lea somewhere before being used.
     
  9. saxman

    saxman

    Oldbie Tech Member
    Alrighty thank you all. I'll post in this topic if I run across any additional problems.
     
  10. notaz

    notaz

    Tech Member
    32
    0
    6
    This is not quite correct, actually those instructions SET the flags, and Bcc both checks them and decides to jump or not to jump..
     
  11. saxman

    saxman

    Oldbie Tech Member
    Here's another question:

    Code (ASM):
    1.     andi.b  #$C,d0      ; is left/right pressed?
    2.     bne.s   Obj01_Traction  ; if yes, branch
    3.     move.w  inertia(a0),d0
    4.     beq.s   Obj01_Traction
    We're performing AND on the d0 register. Then (I'm assuming) it branches if the d0 register is not zero. Then it moves "inertia" into the d0 register. This is the part that trips me -- it branches if... d0 is zero? Am I guessing right?




    EDIT: Also, here's another silly thing I can't figure out:

    Code (ASM):
    1.     move.w  inertia(a0),d0
    2.     beq.s   Obj01_Traction
    3.     bmi.s   Obj01_SettleLeft
    4.  
    5. ; slow down when facing right and not pressing a direction
    6. ; Obj01_SettleRight:
    7.     sub.w   d5,d0
    8.     bcc.s   +
    I get the top portion before the comments, I just included those to ensure everything is in proper context. The half is where I get lost. The BCC will do a branch if the first operand is less than the second operand in the condition. But what operands are we comparing? I see the subtract d5 from d0. I'm assuming d0 is part of the condition, but what is it being compared to... zero?
     
  12. FraGag

    FraGag

    Tech Member
    Exactly.
    cmp is almost the same as sub, except cmp doesn't store the result anywhere (it only affects the flags), while sub stores the result in its second argument (here, d0). It will branch if d0 is greater than or equal to zero.


    If you're confused by the carry flag, you can also see it as the borrow flag: if the result of sub is negative, the carry/borrow flag will be set.
     
  13. saxman

    saxman

    Oldbie Tech Member
    Ran into another problem:

    Code (ASM):
    1.     move.b  angle(a0),d0
    2.     add.b   d1,d0
    3.     move.w  d0,-(sp)
    4.     bsr.w   CalcRoomInFront
    5.     move.w  (sp)+,d0
    I know what SP is from x86 assembly, but I'm not sure how I'm supposed to read it here. Here's what I'm able to interpret:

    - move "angle" into the d0 register
    - add d1 to d0
    - push d0 into the stack, then move the stack pointer back one position???
    - sub CalcRoomInFront
    - pop value from stack into d0, then advance the stack pointer one position???

    The + and - is guess work. I don't know what they're there for, and that's the problem.
     
  14. FraGag

    FraGag

    Tech Member
    The minus sign before (sp) means to decrement the stack pointer before using it. The plus sign after (sp) means to increment the stack pointer after using it. This is necessary as operations on the stack pointer don't automatically change the stack pointer itself. Predecrementing and postincrementing it is necessary so you won't overwrite previous data.
     
  15. Tweaker

    Tweaker

    Banned
    12,387
    2
    0
    Hrm. I wasn't sure whether it set the flags or not—from looking at the wiki page, I mean—so I just said "check" to make sure. I mean, it wouldn't set that flag unless the value was zero, right?

    Damn it all, this topic is making me look dumb XD

    Oh, and saxman, I believe that is simply pushing an address onto the stack for temporary storage, then putting it back into d0 after CalcRoomInFront has been called. It's a quick alternative to storing up to a long of data without taking up a register.
     
  16. saxman

    saxman

    Oldbie Tech Member
    Yet another question

    Code (ASM):
    1.     andi.b  #$C0,d0
    2.     bne.s   return_1A744
    I figure the AND must set the Z flag for the BNE to work with. However, my question is does the Z flag get set based on just the bits you AND, or does it get set for the entire d0 register? In other words, is it based on the entire register being zero, or just bits 7 and 6?
     
  17. It gets set on the entire register being 0, but then the AND modifies the entire register, since ANDing by $C0 implies that all bits other than 7 and 6 will be 0. In other words, just bits 7 and 6 being 0 and the whole register being 0 are the same thing.

    EDIT: Whoops, misread your question slightly. If by entire register you mean all four bytes of the register, I believe it's just based on the byte that you do AND, not the other bytes of the register. Not sure though.
     
  18. saxman

    saxman

    Oldbie Tech Member
    ... rethinking my question, I think I have the answer. Because regardless how the condition works, when you AND d0, you're getting rid of anything below bit 6, so what those bits were make no difference.
     
  19. saxman

    saxman

    Oldbie Tech Member
    Another question:

    Code (ASM):
    1. Sonic_MoveRight:
    2.     move.w  inertia(a0),d0
    3.     bmi.s   Sonic_TurnRight ; if Sonic is already moving to the left, branch
    4.     bclr    #0,status(a0)
    5.     beq.s   +
    - move inertia to d0
    - if d0 is negative, go to Sonic_TurnRight
    - clear bit 0 of status
    - branch if (something) is 0

    Is it the status that is being conditioned, or is it d0?
     
  20. The status. Both bset and bclr first test the bit they're supposed to modify, set flags appropriately and then modify the bit.