<% function negS() { %>
|
|
neg eax
|
|
jo neg_manageOverflow ; Check if overflow. (0x80000000 is the only case)
|
|
|
|
mov [rdi], rax ; not necessary to adjust so just save and return
|
|
ret
|
|
|
|
neg_manageOverflow: ; Do the operation in 64 bits
|
|
push rsi
|
|
movsx rsi, eax
|
|
neg rsi
|
|
call rawCopyS2L
|
|
pop rsi
|
|
ret
|
|
<% } %>
|
|
|
|
<% function negL() { %>
|
|
add rdi, 8
|
|
add rsi, 8
|
|
call rawNegL
|
|
sub rdi, 8
|
|
sub rsi, 8
|
|
ret
|
|
<% } %>
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;
|
|
; neg
|
|
;;;;;;;;;;;;;;;;;;;;;;
|
|
; Adds two elements of any kind
|
|
; Params:
|
|
; rsi <= Pointer to element to be negated
|
|
; rdi <= Pointer to result
|
|
; [rdi] = -[rsi]
|
|
;;;;;;;;;;;;;;;;;;;;;;
|
|
<%=name%>_neg:
|
|
mov rax, [rsi]
|
|
bt rax, 63 ; Check if is short first operand
|
|
jc neg_l
|
|
|
|
neg_s: ; Operand is short
|
|
<%= negS() %>
|
|
|
|
|
|
neg_l:
|
|
mov [rdi], rax ; Copy the type
|
|
<%= negL() %>
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;
|
|
; rawNeg
|
|
;;;;;;;;;;;;;;;;;;;;;;
|
|
; Negates a value
|
|
; Params:
|
|
; rdi <= Pointer to the long data of result
|
|
; rsi <= Pointer to the long data of element 1
|
|
;
|
|
; [rdi] = - [rsi]
|
|
;;;;;;;;;;;;;;;;;;;;;;
|
|
rawNegL:
|
|
; Compare is zero
|
|
|
|
xor rax, rax
|
|
<% for (let i=0; i<n64; i++) { %>
|
|
cmp [rsi + <%=i*8%>], rax
|
|
jnz doNegate
|
|
<% } %>
|
|
; it's zero so just set to zero
|
|
<% for (let i=0; i<n64; i++) { %>
|
|
mov [rdi + <%=i*8%>], rax
|
|
<% } %>
|
|
ret
|
|
doNegate:
|
|
<% for (let i=0; i<n64; i++) { %>
|
|
mov rax, [q + <%=i*8%>]
|
|
<%= i==0 ? "sub" : "sbb" %> rax, [rsi + <%=i*8%>]
|
|
mov [rdi + <%=i*8%>], rax
|
|
<% } %>
|
|
ret
|