4 restore SSE2 ; this ensures that symbol cannot be forward-referenced
\r
9 iterate <instr,ext>, sqrt,51h, rsqrt,52h, rcp,53h, add,58h, mul,59h, sub,5Ch, min,5Dh, div,5Eh, max,5Fh
\r
10 macro instr#pd? dest*,src*
\r
11 SSE.basic_instruction 66h,ext,16,dest,src
\r
13 macro instr#sd? dest*,src*
\r
14 SSE.basic_instruction 0F2h,ext,8,dest,src
\r
18 iterate <instr,ext>, and,54h, andn,55h, or,56h, xor,57h, unpckl,14h, unpckh,15h
\r
19 macro instr#pd? dest*,src*
\r
20 SSE.basic_instruction 66h,ext,16,dest,src
\r
24 macro cmppd? dest*,src*,code*
\r
25 SSE.basic_instruction_imm8 66h,0C2h,16,dest,src,code
\r
28 macro SSE.cmpsd? dest*,src*,code*
\r
29 SSE.basic_instruction_imm8 0F2h,0C2h,8,dest,src,code
\r
32 calminstruction cmpsd? args&
\r
39 arrange args, =SSE.=cmpsd args
\r
43 iterate <cond,code>, eq,0, lt,1, le,2, unord,3, neq,4, nlt,5, nle,6, ord,7
\r
44 macro cmp#cond#pd? dest*,src*
\r
47 macro cmp#cond#sd? dest*,src*
\r
52 macro shufpd? dest*,src*,imm*
\r
53 SSE.basic_instruction_imm8 66h,0C6h,16,dest,src,imm
\r
56 iterate <instr,ext>, movapd,28h, movupd,10h
\r
57 macro instr? dest*,src*
\r
58 SSE.parse_operand @dest,dest
\r
59 SSE.parse_operand @src,src
\r
60 if (@dest.size or @src.size) and not 16
\r
61 err 'invalid operand size'
\r
63 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
64 @src.opcode_prefix = 66h
\r
65 x86.store_instruction <0Fh,ext>,@src,@dest.rm
\r
66 else if @dest.type = 'mem' & @src.type = 'mmreg'
\r
67 @dest.opcode_prefix = 66h
\r
68 x86.store_instruction <0Fh,ext+1>,@dest,@src.rm
\r
70 err 'invalid combination of operands'
\r
75 iterate <instr,ext>, movlpd,12h, movhpd,16h
\r
76 macro instr? dest*,src*
\r
77 SSE.parse_operand @dest,dest
\r
78 SSE.parse_operand @src,src
\r
79 if @dest.type = 'mmreg' & @src.type = 'mem'
\r
80 if @dest.size <> 16 | @src.size and not 8
\r
81 err 'invalid operand size'
\r
83 @src.opcode_prefix = 66h
\r
84 x86.store_instruction <0Fh,ext>,@src,@dest.rm
\r
85 else if @dest.type = 'mem' & @src.type = 'mmreg'
\r
86 if @dest.size and not 8 | @src.size <> 16
\r
87 err 'invalid operand size'
\r
89 @dest.opcode_prefix = 66h
\r
90 x86.store_instruction <0Fh,ext+1>,@dest,@src.rm
\r
92 err 'invalid combination of operands'
\r
97 macro SSE.movsd? dest*,src*
\r
98 SSE.parse_operand @dest,dest
\r
99 SSE.parse_operand @src,src
\r
100 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
101 if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> 16)
\r
102 err 'invalid operand size'
\r
104 @src.opcode_prefix = 0F2h
\r
105 x86.store_instruction <0Fh,10h>,@src,@dest.rm
\r
106 else if @dest.type = 'mem' & @src.type = 'mmreg'
\r
107 if @dest.size and not 8 | @src.size <> 16
\r
108 err 'invalid operand size'
\r
110 @dest.opcode_prefix = 0F2h
\r
111 x86.store_instruction <0Fh,11h>,@dest,@src.rm
\r
113 err 'invalid combination of operands'
\r
117 calminstruction movsd? args&
\r
124 arrange args, =SSE.=movsd args
\r
126 end calminstruction
\r
128 iterate <instr,pre>, movdqa,66h, movdqu,0F3h
\r
129 macro instr? dest*,src*
\r
130 SSE.parse_operand @dest,dest
\r
131 SSE.parse_operand @src,src
\r
132 if (@dest.size or @src.size) and not 16
\r
133 err 'invalid operand size'
\r
135 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
136 @src.opcode_prefix = pre
\r
137 x86.store_instruction <0Fh,6Fh>,@src,@dest.rm
\r
138 else if @dest.type = 'mem' & @src.type = 'mmreg'
\r
139 @dest.opcode_prefix = pre
\r
140 x86.store_instruction <0Fh,7Fh>,@dest,@src.rm
\r
142 err 'invalid combination of operands'
\r
147 iterate <instr,ext>, movntpd,2Bh, movntdq,0E7h
\r
148 macro instr? dest*,src*
\r
149 SSE.parse_operand @dest,dest
\r
150 SSE.parse_operand @src,src
\r
151 if @dest.type = 'mem' & @src.type = 'mmreg'
\r
152 if (@dest.size or @src.size) and not 16
\r
153 err 'invalid operand size'
\r
155 @dest.opcode_prefix = 66h
\r
156 x86.store_instruction <0Fh,ext>,@dest,@src.rm
\r
158 err 'invalid combination of operands'
\r
163 macro movmskpd? dest*,src*
\r
164 SSE.parse_operand @dest,dest
\r
165 SSE.parse_operand @src,src
\r
166 if @dest.type = 'reg' & @src.type = 'mmreg'
\r
167 if (@dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)) | @src.size <> 16
\r
168 err 'invalid operand size'
\r
170 @src.opcode_prefix = 66h
\r
171 x86.store_instruction <0Fh,50h>,@src,@dest.rm
\r
173 err 'invalid combination of operands'
\r
177 macro maskmovdqu? dest*,src*
\r
178 SSE.parse_operand @dest,dest
\r
179 SSE.parse_operand @src,src
\r
180 if @dest.type = 'mmreg' & @src.type = 'mmreg'
\r
181 if (@dest.size or @src.size) <> 16
\r
182 err 'invalid operand size'
\r
184 @src.opcode_prefix = 66h
\r
185 x86.store_instruction <0Fh,0F7h>,@src,@dest.rm
\r
187 err 'invalid combination of operands'
\r
191 iterate <instr,ext>, ucomisd,2Eh, comisd,2Fh
\r
192 macro instr? dest*,src*
\r
193 SSE.parse_operand @dest,dest
\r
194 SSE.parse_operand @src,src
\r
195 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
196 if @dest.size <> 16 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> 16)
\r
197 err 'invalid operand size'
\r
199 @src.opcode_prefix = 66h
\r
200 x86.store_instruction <0Fh,ext>,@src,@dest.rm
\r
202 err 'invalid combination of operands'
\r
207 macro cvtps2pd? dest*,src*
\r
208 SSE.basic_instruction 0,5Ah,8,dest,src
\r
211 macro cvtpd2ps? dest*,src*
\r
212 SSE.basic_instruction 66h,5Ah,16,dest,src
\r
215 macro cvtsd2ss? dest*,src*
\r
216 SSE.basic_instruction 0F2h,5Ah,8,dest,src
\r
219 macro cvtss2sd? dest*,src*
\r
220 SSE.basic_instruction 0F3h,5Ah,4,dest,src
\r
223 macro cvtdq2ps? dest*,src*
\r
224 SSE.basic_instruction 0,5Bh,16,dest,src
\r
227 macro cvtps2dq? dest*,src*
\r
228 SSE.basic_instruction 66h,5Bh,16,dest,src
\r
231 macro cvttps2dq? dest*,src*
\r
232 SSE.basic_instruction 0F3h,5Bh,16,dest,src
\r
235 macro cvttpd2dq? dest*,src*
\r
236 SSE.basic_instruction 66h,0E6h,16,dest,src
\r
239 macro cvtpd2dq? dest*,src*
\r
240 SSE.basic_instruction 0F2h,0E6h,16,dest,src
\r
243 macro cvtdq2pd? dest*,src*
\r
244 SSE.basic_instruction 0F3h,0E6h,8,dest,src
\r
247 macro movdq2q? dest*,src*
\r
248 SSE.parse_operand @dest,dest
\r
249 SSE.parse_operand @src,src
\r
250 if @dest.type = 'mmreg' & @src.type = 'mmreg'
\r
251 if @dest.size <> 8 | @src.size <> 16
\r
252 err 'invalid operand size'
\r
254 @src.opcode_prefix = 0F2h
\r
255 x86.store_instruction <0Fh,0D6h>,@src,@dest.rm
\r
257 err 'invalid combination of operands'
\r
261 macro movq2dq? dest*,src*
\r
262 SSE.parse_operand @dest,dest
\r
263 SSE.parse_operand @src,src
\r
264 if @dest.type = 'mmreg' & @src.type = 'mmreg'
\r
265 if @dest.size <> 16 | @src.size <> 8
\r
266 err 'invalid operand size'
\r
268 @src.opcode_prefix = 0F3h
\r
269 x86.store_instruction <0Fh,0D6h>,@src,@dest.rm
\r
271 err 'invalid combination of operands'
\r
275 macro cvtpi2pd? dest*,src*
\r
276 SSE.parse_operand @dest,dest
\r
277 SSE.parse_operand @src,src
\r
278 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
279 if @dest.size <> 16 | @src.size and not 8
\r
280 err 'invalid operand size'
\r
282 @src.opcode_prefix = 66h
\r
283 x86.store_instruction <0Fh,2Ah>,@src,@dest.rm
\r
285 err 'invalid combination of operands'
\r
289 macro cvtsi2sd? dest*,src*
\r
290 SSE.parse_operand @dest,dest
\r
291 x86.parse_operand @src,src
\r
292 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg')
\r
294 err 'operand size not specified'
\r
295 else if @dest.size <> 16 | @src.size < 4
\r
296 err 'invalid operand size'
\r
298 x86.select_operand_prefix @src,@src.size
\r
299 @src.opcode_prefix = 0F2h
\r
300 x86.store_instruction <0Fh,2Ah>,@src,@dest.rm
\r
302 err 'invalid combination of operands'
\r
306 iterate <instr,ext>, cvttpd2pi,2Ch, cvtpd2pi,2Dh
\r
307 macro instr? dest*,src*
\r
308 SSE.parse_operand @dest,dest
\r
309 SSE.parse_operand @src,src
\r
310 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
311 if @dest.size <> 8 | @src.size and not 16
\r
312 err 'invalid operand size'
\r
314 @src.opcode_prefix = 66h
\r
315 x86.store_instruction <0Fh,ext>,@src,@dest.rm
\r
317 err 'invalid combination of operands'
\r
322 iterate <instr,ext>, cvttsd2si,2Ch, cvtsd2si,2Dh
\r
323 macro instr? dest*,src*
\r
324 x86.parse_operand @dest,dest
\r
325 SSE.parse_operand @src,src
\r
326 if @dest.type = 'reg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
327 if @dest.size < 4 | (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <>16)
\r
328 err 'invalid operand size'
\r
330 x86.select_operand_prefix @src,@dest.size
\r
331 @src.opcode_prefix = 0F2h
\r
332 x86.store_instruction <0Fh,ext>,@src,@dest.rm
\r
334 err 'invalid combination of operands'
\r
339 calminstruction MMX.select_operand_prefix rm_operand*,size*
\r
343 compute prefix, 66h
\r
344 arrange sym, rm_operand.=prefix
\r
345 publish sym, prefix
\r
350 asmcmd =err 'invalid operand size'
\r
352 end calminstruction
\r
354 calminstruction MMX.basic_instruction ext,dest,src
\r
355 asmcmd =SSE.=parse_operand =@dest,dest
\r
356 asmcmd =SSE.=parse_operand =@src,src
\r
357 check @src.size and not @dest.size
\r
359 asmcmd =err 'operand sizes do not match'
\r
361 check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
362 jno invalid_combination_of_operands
\r
363 asmcmd =MMX.=select_operand_prefix =@src,=@dest.=size
\r
364 asmcmd =x86.=store_instruction <0Fh,ext>,=@src,=@dest.=rm
\r
366 invalid_combination_of_operands:
\r
367 asmcmd =err 'invalid combination of operands'
\r
368 end calminstruction
\r
370 calminstruction MMX.bit_shift_instruction ext,dest,src
\r
371 asmcmd =SSE.=parse_operand =@dest,dest
\r
372 asmcmd =SSE.=parse_operand =@src,src
\r
373 check @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
375 check @dest.type = 'mmreg' & @src.type = 'imm'
\r
377 asmcmd =err 'invalid combination of operands'
\r
380 check @src.size and not @dest.size
\r
382 asmcmd =err 'operand sizes do not match'
\r
384 asmcmd =MMX.=select_operand_prefix =@src,=@dest.=size
\r
385 asmcmd =x86.=store_instruction <0Fh,ext>,=@src,=@dest.=rm
\r
388 check @src.size and not 1
\r
390 asmcmd =err 'invalid operand size'
\r
393 compute iext, 70h+(ext and 0Fh)
\r
394 compute irm, ((ext shr 4)-0Ch) shl 1
\r
395 asmcmd =MMX.=select_operand_prefix =@dest,=@dest.=size
\r
396 asmcmd =x86.=store_instruction <0Fh,iext>,=@dest,irm,1,=@src.=imm
\r
397 end calminstruction
\r
399 iterate <instr,ext>, paddq,0D4h, pmuludq,0F4h, psubq,0FBh
\r
400 macro instr? dest*,src*
\r
401 MMX.basic_instruction ext,dest,src
\r
405 macro movq? dest*,src*
\r
406 SSE.parse_operand @dest,dest
\r
407 SSE.parse_operand @src,src
\r
408 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
409 if (@src.type = 'mem' & @src.size and not 8) | (@src.type = 'mmreg' & @src.size <> @dest.size)
\r
410 err 'invalid operand size'
\r
413 x86.store_instruction <0Fh,6Fh>,@src,@dest.rm
\r
415 @src.opcode_prefix = 0F3h
\r
416 x86.store_instruction <0Fh,7Eh>,@src,@dest.rm
\r
418 else if @dest.type = 'mem' & @src.type = 'mmreg'
\r
419 if @dest.size and not 8
\r
420 err 'invalid operand size'
\r
423 x86.store_instruction <0Fh,7Fh>,@dest,@src.rm
\r
425 @dest.opcode_prefix = 66h
\r
426 x86.store_instruction <0Fh,0D6h>,@dest,@src.rm
\r
428 else if @dest.type = 'reg' & @src.type = 'mmreg'
\r
430 err 'invalid operand size'
\r
433 @dest.opcode_prefix = 66h
\r
436 x86.store_instruction <0Fh,7Eh>,@dest,@src.rm
\r
437 else if @dest.type = 'mmreg' & @src.type = 'reg'
\r
439 err 'invalid operand size'
\r
442 @src.opcode_prefix = 66h
\r
445 x86.store_instruction <0Fh,6Eh>,@src,@dest.rm
\r
447 err 'invalid combination of operands'
\r
451 macro movd? dest*,src*
\r
452 SSE.parse_operand @dest,dest
\r
453 SSE.parse_operand @src,src
\r
454 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'reg')
\r
455 if @src.size and not 4
\r
456 err 'invalid operand size'
\r
458 MMX.select_operand_prefix @src,@dest.size
\r
459 x86.store_instruction <0Fh,6Eh>,@src,@dest.rm
\r
460 else if (@dest.type = 'mem' | @dest.type = 'reg') & @src.type = 'mmreg'
\r
461 if @dest.size and not 4
\r
462 err 'invalid operand size'
\r
464 MMX.select_operand_prefix @dest,@src.size
\r
465 x86.store_instruction <0Fh,7Eh>,@dest,@src.rm
\r
467 err 'invalid combination of operands'
\r
471 macro pinsrw? dest*,src*,sel*
\r
472 SSE.parse_operand @dest,dest
\r
473 x86.parse_operand @src,src
\r
474 x86.parse_operand @aux,sel
\r
475 if @dest.type = 'mmreg' & (@src.type = 'reg' | @src.type = 'mem') & @aux.type = 'imm'
\r
476 if (@src.type = 'reg' & @src.size <> 4) | (@src.type = 'mem' & @src.size and not 2) | @aux.size and not 1
\r
477 err 'invalid operand size'
\r
479 MMX.select_operand_prefix @src,@dest.size
\r
480 x86.store_instruction <0Fh,0C4h>,@src,@dest.rm,1,@aux.imm
\r
482 err 'invalid combination of operands'
\r
486 macro pextrw? dest*,src*,sel*
\r
487 x86.parse_operand @dest,dest
\r
488 SSE.parse_operand @src,src
\r
489 x86.parse_operand @aux,sel
\r
490 if @dest.type = 'reg' & @src.type = 'mmreg' & @aux.type = 'imm'
\r
491 if x86.mode = 64 & @dest.size = 8
\r
494 if @dest.size <> 4 | @aux.size and not 1
\r
495 err 'invalid operand size'
\r
497 MMX.select_operand_prefix @src,@src.size
\r
498 x86.store_instruction <0Fh,0C5h>,@src,@dest.rm,1,@aux.imm
\r
500 err 'invalid combination of operands'
\r
504 iterate <instr,pre>, pshufd,66h, pshuflw,0F2h, pshufhw,0F3h
\r
505 macro instr? dest*,src*,sel*
\r
506 SSE.parse_operand @dest,dest
\r
507 SSE.parse_operand @src,src
\r
508 x86.parse_operand @aux,sel
\r
509 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg') & @aux.type = 'imm'
\r
510 if @dest.size <> 16 | @src.size and not 16 | @aux.size and not 1
\r
511 err 'invalid operand size'
\r
513 @src.opcode_prefix = pre
\r
514 x86.store_instruction <0Fh,70h>,@src,@dest.rm,1,@aux.imm
\r
516 err 'invalid combination of operands'
\r
521 macro pmovmskb? dest*,src*
\r
522 x86.parse_operand @dest,dest
\r
523 SSE.parse_operand @src,src
\r
524 if @dest.type = 'reg' & @src.type = 'mmreg'
\r
525 if @dest.size <> 4 & (x86.mode < 64 | @dest.size <> 8)
\r
526 err 'invalid operand size'
\r
528 MMX.select_operand_prefix @src,@src.size
\r
529 x86.store_instruction <0Fh,0D7h>,@src,@dest.rm
\r
531 err 'invalid combination of operands'
\r
535 iterate <instr,postbyte>, psrldq,3, pslldq,7
\r
536 macro instr? dest*,cnt*
\r
537 SSE.parse_operand @dest,dest
\r
538 x86.parse_operand @aux,cnt
\r
539 if @dest.type = 'mmreg' & @aux.type = 'imm'
\r
540 if @dest.size <> 16 | @aux.size and not 1
\r
541 err 'invalid operand size'
\r
543 @dest.opcode_prefix = 66h
\r
544 x86.store_instruction <0Fh,73h>,@dest,postbyte,1,@aux.imm
\r
546 err 'invalid combination of operands'
\r
551 iterate <instr,ext>, punpcklqdq,6Ch, punpckhqdq,6Dh
\r
552 macro instr? dest*,src*
\r
553 SSE.parse_operand @dest,dest
\r
554 SSE.parse_operand @src,src
\r
555 if @dest.type = 'mmreg' & (@src.type = 'mem' | @src.type = 'mmreg')
\r
556 if (@dest.size or @src.size) and not 16
\r
557 err 'invalid operand size'
\r
559 @src.opcode_prefix = 66h
\r
560 x86.store_instruction <0Fh,ext>,@src,@dest.rm
\r
562 err 'invalid combination of operands'
\r
567 macro movnti? dest*,src*
\r
568 x86.parse_operand @dest,dest
\r
569 x86.parse_operand @src,src
\r
570 if @dest.type = 'mem' & @src.type = 'reg'
\r
571 if @dest.size and not @src.size
\r
572 err 'operand sizes do not match'
\r
573 else if @src.size <> 4 & @src.size <> 8
\r
574 err 'invalid operand size'
\r
576 x86.select_operand_prefix @dest,@src.size
\r
577 x86.store_instruction <0Fh,0C3h>,@dest,@src.rm
\r
579 err 'invalid combination of operands'
\r
583 macro clflush? src*
\r
584 x86.parse_operand @src,src
\r
585 if @src.type = 'mem'
\r
586 if @src.size and not 1
\r
587 err 'invalid operand size'
\r
589 x86.store_instruction <0Fh,0AEh>,@src,7
\r
591 err 'invalid operand'
\r