Page 4 of 6

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 1:33 am
by Tenaja
idle wrote:I'm spamming the thread now might have to moderate myself;
I don't have an x86 vm setup at the moment or windows either

so this should hopefully work now and I'll go back and edit my spam !

Code: Select all

CompilerIf SizeOf(Integer) = 8 
  Macro edx : rdx : EndMacro 
CompilerEndIf 

Macro EnableUnsigned() 
  
  !macro IDIV var
  !{ 
     !xor edx,edx 
     !div var
  !} 
  !macro SAR reg,var 
  !{
    !shr reg,var 
  !} 
  
  !macro SAL reg,var 
  !{ 
   !shl reg,var 
  !}
  
EndMacro

Macro DisableUnsigned() 
  !purge IDIV
  !purge SAR
  !purge SAL 
  UndefineMacro EnableUnsigned 
EndMacro   

Procedure Unsigned(arg1.i,op1.l,arg2.i) 
   
  Select op1 
    Case '<'
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setb al 
      ProcedureReturn 
    Case '<='   
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setbe al 
       ProcedureReturn 
    Case '>'  
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !seta al 
      ProcedureReturn
    Case '>='  
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setae al 
       ProcedureReturn 
     Case '=' 
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !sete al 
      ProcedureReturn
    Case '<>' 
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setne al 
      ProcedureReturn
  EndSelect     
EndProcedure     
  

x.l=$FFFFFFFF
y.l=$FFFFFFFE

If Unsigned(x,'>=',y/2) ; unsigned comparison.
  Debug "OK"
  EnableUnsigned() 
  Debug y / 2
  y<<1
  DisableUnsigned()
  Debug y / 2
  
EndIf
Can you post your final working code in Tips & Tricks?

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 2:12 am
by idle
@Tenaja, yes once it's working properly!
there are still some issues to resolve, think I've sorted the unsigned macro
but I'm still trying to get the unsigned div to work

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 3:07 am
by Keya
BRILLIANT WORK, IDLE!!!!!!!!!!!! :) :) :)
only just got to test it a second ago but looks good!!!
operators, evaluations... but also some functions!? im not sure how many

Code: Select all

  EnableUnsigned()
  Debug y / 2        ;Good (unsigned)
  Debug Str(y / 2)   ;Bad(?) (signed)

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 4:52 am
by idle
it might be ok now I'm was trying to work out how to patch MOVSXD with an fasm macro

pb outputs

Code: Select all

 MOVSXD r15,dword [v_y]
  MOV    rax,r15
  MOV    rcx,2
  CQO
  IDIV   rcx
  MOV    r15,rax
which creates a problem sign extending the input, I tried substituting it with lea but that didn't work out
so I resorted to a match which might be ok!

it's currently working for x64 don't know for x86 might need adapting

Code: Select all

CompilerIf SizeOf(Integer) = 8 
  Macro edx : rdx : EndMacro 
CompilerElse 
  Macro rax : eax : EndMacro 
CompilerEndIf 

Macro EnableUnsigned() 
  
  !macro IDIV var
  !{ 
     !mov edx,0 
     !div var
  !} 
  !macro SAR reg,var 
  !{
    !shr reg,var 
  !} 
  
  !macro SAL reg,var 
  !{ 
   !shl reg,var 
  !}
    
  !macro MOVSXD reg,var  
  !{ 
  !match =dword x , var 
  !\{ mov eax, var 
    !mov reg,rax \} 
  !} 
EndMacro

Macro DisableUnsigned() 
  !purge IDIV
  !purge SAR
  !purge SAL 
  !purge MOVSXD
  
  UndefineMacro EnableUnsigned 
EndMacro   

Procedure Unsigned(arg1.i,op1.l,arg2.i) 
  EnableASM 
  
  Select op1 
    Case '<'
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setb al 
      ProcedureReturn 
    Case '<='   
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setbe al 
      ProcedureReturn 
    Case '>'  
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !seta al 
      ProcedureReturn
    Case '>='  
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setae al 
      ProcedureReturn 
     Case '=' 
      !xor rax,rax 
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !sete al 
      ProcedureReturn
    Case '<>' 
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setne al 
      ProcedureReturn
  EndSelect     
EndProcedure     
  

Global x.l,y.l 
x=$1
y=$FFFFFFFE
Debug y ;Hex(y,#PB_Long)
y / 2
Debug y ;Hex(y,#PB_Long) 

EnableUnsigned()

y=$FFFFFFFE

If Unsigned(x,'<=',y) ; unsigned comparison.
  Debug "OK"
  y / 2
  Debug y ;Hex(y,#PB_Long)   ;7FFFFFFF
  y << 1
  Debug y ;Hex(y ,#PB_Long)  ;FFFFFFFE 
  
  DisableUnsigned()
  Debug y
  y / 2 
  Debug y ;Hex(y,#PB_Long)
  
EndIf

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 5:46 am
by Thunder93
PureBasic.asm [274]:
xor rax, rax
error: illegal instruction.

PBx86 under Win x64
-----------

Debug Output from PBx64:

Code: Select all

FFFFFFFE
FFFFFFFF
OK
2147483647
4294967294
-1

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 6:04 am
by wilbert
Replacing asm instructions like this would be highly unpredictable and unstable.
There might be places in the source code where PB outputs one of these instructions where you don't expect it.
Also for example the macro for IDIV. You are replacing edx with zero. But when you do a quad division on x86, edx might be used also (not sure).
Separate procedures for different unsigned operations are a much better approach.

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 6:06 am
by idle
try changing this compilerif

Code: Select all

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86  
  Macro rax : eax : EndMacro
CompilerElse 
  Macro edx : rdx : EndMacro 
CompilerEndIf 

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 6:19 am
by Thunder93
Tried.

Code: Select all

PureBasic.asm [259]:
xor rax, rax
error: illegal instruction.

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 6:19 am
by wilbert
Here's my simple suggestion for comparing

Code: Select all

Procedure UComp(a.i, b.i)
  ; output -1 when a < b
  ; output  0 when a = b
  ; output  1 when a > b
  CompilerIf SizeOf(Integer) = 8
    !mov rdx, [p.v_a]
    !cmp rdx, [p.v_b]
    !setnz dl
    !sbb rax, rax
  CompilerElse
    !mov edx, [p.v_a]
    !cmp edx, [p.v_b]
    !setnz dl
    !sbb eax, eax
  CompilerEndIf
  !or al, dl
  ProcedureReturn
EndProcedure

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 6:56 am
by idle
wilbert wrote:Replacing asm instructions like this would be highly unpredictable and unstable.
There might be places in the source code where PB outputs one of these instructions where you don't expect it.
Also for example the macro for IDIV. You are replacing edx with zero. But when you do a quad division on x86, edx might be used also (not sure).
Separate procedures for different unsigned operations are a much better approach.
It's easy enough to make regular pb macros to do it, but it doesn't fit syntactically with what people want.
the only issue I think for unpredictability would be with movsxd but as long as the macro is enabled and disabled appropriately
it should trap it.

zeroing edx / rdx should be fine for the native integer size, as for unsigned quads on x86 yes it will probably need another approach but is it really needed?
The issues with signed types only rears it self on pointer arithmetic (native size) and passing to the odd lib function.

are there other ops to consider than movsx idiv and the tests on flags from cmp?

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 7:14 am
by wilbert
idle wrote:are there other ops to consider than movsx idiv and the tests on flags from cmp?
CWD, CDQ, CQO, maybe IMUL

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 11:07 am
by idle
not sure if fasm macros will eat CQO and related ops, will have to check the disassembly
here's the latest, x64 only at the moment

Code: Select all

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86  
  Macro rax : eax : EndMacro
CompilerElse 
  Macro edx : rdx : EndMacro 
CompilerEndIf 

Macro EnableUnsigned() 
  
  !macro IDIV var
  !{ 
     !mov edx,0 
     !div var
  !}
  
  !macro IMUL reg,var
  !{
    !mul reg
    !mov reg,rax 
  !}  
  
  !macro SAR reg,var 
  !{
    !shr reg,var 
  !} 
  
  !macro SAL reg,var 
  !{ 
   !shl reg,var 
  !}
    
  !macro MOVSXD reg,var  
  !{ 
    !match =dword x , var 
    !\{ mov eax, var 
       !mov reg,rax \} 
    !} 
  !macro CQO {}
  !macro CDO {}
  !macro CWD {} 
  !macro CBW {}
  !macro CWDE{}
  !macro CDQE {} 
EndMacro

Macro DisableUnsigned() 
  !purge IDIV
  !purge IMUL
  !purge SAR
  !purge SAL 
  !purge MOVSXD
  !purge CQO 
  !purge CDO
  !purge CWD 
  !purge CBW
  !purge CWDE 
  !purge CDQE 
  UndefineMacro EnableUnsigned 
EndMacro   

Procedure Unsigned(arg1.i,op1.l,arg2.i) 
  EnableASM 
  
  Select op1 
    Case '<'
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setb al 
      ProcedureReturn 
    Case '<='   
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setbe al 
      ProcedureReturn 
    Case '>'  
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !seta al 
      ProcedureReturn
    Case '>='  
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setae al 
      ProcedureReturn 
     Case '=' 
      !xor rax,rax 
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !sete al 
      ProcedureReturn
    Case '<>' 
      !xor rax,rax
      !mov edx, [p.v_arg1]
      !cmp edx, [p.v_arg2] 
      !setne al 
      ProcedureReturn
  EndSelect     
EndProcedure     
  

Global x.l,y.l 
x=2
y=$FFFFFFFE
Debug y 
y / 2
Debug y  

EnableUnsigned()

y=$FFFFFFFE

If Unsigned(x,'<=',y) ; unsigned comparison.
  Debug "OK"
  y / 2
  Debug y ;Hex(y,#PB_Long)   ;7FFFFFFF
  y * x
  Debug y ;Hex(y ,#PB_Long)  ;FFFFFFFE 
  y >> 1 
  Debug y ;Hex(y ,#PB_Long)  ;FFFFFFFE 
  y << 1 
  Debug y
  y - x 
  Debug y
  y + x 
  Debug Str(y)
  DisableUnsigned()
  Debug Str(y)
  y / 2 
  Debug y ;Hex(y,#PB_Long)
  
EndIf

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 11:11 am
by Keya
i dont understand why it's complaining about "illegal instruction: xor rax, rax" in x86 because the rax->eax macro is supposed to take care of that. Weird!
Anyway I did a manual global replace of 'rax' to 'eax', and removed the eax macro, and it compiles and outputs:

Code: Select all

-2
-1
OK
2147483647
-2147348480
1073809408
-2147348480
-2147348482
-2147348480
-2147348480
-1073674240

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 11:17 am
by wilbert
Keya wrote:i dont understand why it's complaining about "illegal instruction: xor rax, rax" in x86 because the rax->eax macro is supposed to take care of that.
That macro substituting rax with eax, only works for lines of code without an exclamation mark.
So you would have to replace all !xor rax,rax with xor rax,rax

Re: Unsigned dword/qword

Posted: Thu Mar 24, 2016 11:19 am
by Keya
spot on wilbert! :) i just simply replaced "! xor rax, rax" with "xor rax, rax" as per your suggestion and it compiles smoothly now