1/*
2 *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 *  This program is free software; you can redistribute it and/or modify
5 *  it under the terms of the GNU General Public License as published by
6 *  the Free Software Foundation; either version 2 of the License, or
7 *  (at your option) any later version.
8 *
9 *  This program is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 *  GNU General Public License for more details.
13 *
14 *  You should have received a copy of the GNU General Public License
15 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18DEF_MACRO(fDUMPQ,
19	do {
20		printf(STR ":" #REG ": 0x%016llx\n",REG.ud[0]);
21	} while (0),
22	()
23)
24
25DEF_MACRO(fUSE_LOOKUP_ADDRESS_BY_REV,
26	PROC->arch_proc_options->mmvec_use_full_va_for_lookup,
27	()
28)
29
30DEF_MACRO(fUSE_LOOKUP_ADDRESS,
31	1,
32	()
33)
34
35DEF_MACRO(fNOTQ,
36	({mmqreg_t _ret = {0}; int _i_; for (_i_ = 0; _i_ < fVECSIZE()/64; _i_++) _ret.ud[_i_] = ~VAL.ud[_i_]; _ret;}),
37	()
38)
39
40DEF_MACRO(fGETQBITS,
41	((MASK) & (REG.w[(BITNO)>>5] >> ((BITNO) & 0x1f))),
42	()
43)
44
45DEF_MACRO(fGETQBIT,
46	fGETQBITS(REG,1,1,BITNO),
47	()
48)
49
50DEF_MACRO(fGENMASKW,
51	(((fGETQBIT(QREG,(IDX*4+0)) ? 0xFF : 0x0) << 0)
52	|((fGETQBIT(QREG,(IDX*4+1)) ? 0xFF : 0x0) << 8)
53	|((fGETQBIT(QREG,(IDX*4+2)) ? 0xFF : 0x0) << 16)
54	|((fGETQBIT(QREG,(IDX*4+3)) ? 0xFF : 0x0) << 24)),
55	()
56)
57DEF_MACRO(fGET10BIT,
58	{
59		COE = (((((fGETUBYTE(3,VAL) >> (2 * POS)) & 3) << 8) | fGETUBYTE(POS,VAL)) << 6);
60		COE >>= 6;
61	},
62	()
63)
64
65DEF_MACRO(fVMAX,
66	(X>Y) ? X : Y,
67	()
68)
69
70
71DEF_MACRO(fGETNIBBLE,
72    ( fSXTN(4,8,(SRC >> (4*IDX)) & 0xF) ),
73    ()
74)
75
76DEF_MACRO(fGETCRUMB,
77    ( fSXTN(2,8,(SRC >> (2*IDX)) & 0x3) ),
78    ()
79)
80
81DEF_MACRO(fGETCRUMB_SYMMETRIC,
82    ( (fGETCRUMB(IDX,SRC)>=0 ? (2-fGETCRUMB(IDX,SRC)) : fGETCRUMB(IDX,SRC) ) ),
83    ()
84)
85
86#define ZERO_OFFSET_2B +
87
88DEF_MACRO(fGENMASKH,
89	(((fGETQBIT(QREG,(IDX*2+0)) ? 0xFF : 0x0) << 0)
90	|((fGETQBIT(QREG,(IDX*2+1)) ? 0xFF : 0x0) << 8)),
91	()
92)
93
94DEF_MACRO(fGETMASKW,
95	(VREG.w[IDX] & fGENMASKW((QREG),IDX)),
96	()
97)
98
99DEF_MACRO(fGETMASKH,
100	(VREG.h[IDX] & fGENMASKH((QREG),IDX)),
101	()
102)
103
104DEF_MACRO(fCONDMASK8,
105	(fGETQBIT(QREG,IDX) ? (YESVAL) : (NOVAL)),
106	()
107)
108
109DEF_MACRO(fCONDMASK16,
110	((fGENMASKH(QREG,IDX) & (YESVAL)) | (fGENMASKH(fNOTQ(QREG),IDX) & (NOVAL))),
111	()
112)
113
114DEF_MACRO(fCONDMASK32,
115	((fGENMASKW(QREG,IDX) & (YESVAL)) | (fGENMASKW(fNOTQ(QREG),IDX) & (NOVAL))),
116	()
117)
118
119
120DEF_MACRO(fSETQBITS,
121	do {
122		size4u_t __TMP = (VAL);
123		REG.w[(BITNO)>>5] &= ~((MASK) << ((BITNO) & 0x1f));
124		REG.w[(BITNO)>>5] |= (((__TMP) & (MASK)) << ((BITNO) & 0x1f));
125	} while (0),
126	()
127)
128
129DEF_MACRO(fSETQBIT,
130	fSETQBITS(REG,1,1,BITNO,VAL),
131	()
132)
133
134DEF_MACRO(fVBYTES,
135	(fVECSIZE()),
136	()
137)
138
139DEF_MACRO(fVHALVES,
140	(fVECSIZE()/2),
141	()
142)
143
144DEF_MACRO(fVWORDS,
145	(fVECSIZE()/4),
146	()
147)
148
149DEF_MACRO(fVDWORDS,
150	(fVECSIZE()/8),
151	()
152)
153
154DEF_MACRO(fVALIGN,
155    ( ADDR = ADDR & ~(LOG2_ALIGNMENT-1)),
156    ()
157)
158
159DEF_MACRO(fVLASTBYTE,
160    ( ADDR = ADDR | (LOG2_ALIGNMENT-1)),
161    ()
162)
163
164
165DEF_MACRO(fVELEM,
166    ((fVECSIZE()*8)/WIDTH),
167    ()
168)
169
170DEF_MACRO(fVECLOGSIZE,
171    (mmvec_current_veclogsize(thread)),
172    ()
173)
174
175DEF_MACRO(fVECSIZE,
176    (1<<fVECLOGSIZE()),
177    ()
178)
179
180DEF_MACRO(fSWAPB,
181    {
182		size1u_t tmp = A;
183		A = B;
184		B = tmp;
185	},
186    /* NOTHING */
187)
188
189DEF_MACRO(
190	fVZERO,
191	mmvec_zero_vector(),
192	()
193)
194
195DEF_MACRO(
196    fNEWVREG,
197    ((THREAD2STRUCT->VRegs_updated & (((VRegMask)1)<<VNUM)) ? THREAD2STRUCT->future_VRegs[VNUM] : mmvec_zero_vector()),
198    (A_DOTNEWVALUE,A_RESTRICT_SLOT0ONLY)
199)
200
201DEF_MACRO(
202	fV_AL_CHECK,
203	if ((EA) & (MASK)) {
204		warn("aligning misaligned vector. PC=%08x EA=%08x",thread->Regs[REG_PC],(EA));
205	},
206	()
207)
208DEF_MACRO(fSCATTER_INIT,
209    {
210    mem_vector_scatter_init(thread, insn,   REGION_START, LENGTH, ELEMENT_SIZE);
211	if (EXCEPTION_DETECTED) return;
212    },
213    (A_STORE,A_MEMLIKE,A_RESTRICT_SLOT0ONLY)
214)
215
216DEF_MACRO(fGATHER_INIT,
217    {
218    mem_vector_gather_init(thread, insn,   REGION_START, LENGTH, ELEMENT_SIZE);
219	if (EXCEPTION_DETECTED) return;
220    },
221    (A_LOAD,A_MEMLIKE,A_RESTRICT_SLOT1ONLY)
222)
223
224DEF_MACRO(fSCATTER_FINISH,
225    {
226	if (EXCEPTION_DETECTED) return;
227    mem_vector_scatter_finish(thread, insn, OP);
228    },
229    ()
230)
231
232DEF_MACRO(fGATHER_FINISH,
233    {
234	if (EXCEPTION_DETECTED) return;
235    mem_vector_gather_finish(thread, insn);
236    },
237    ()
238)
239
240
241DEF_MACRO(CHECK_VTCM_PAGE,
242     {
243        int slot = insn->slot;
244        paddr_t pa = thread->mem_access[slot].paddr+OFFSET;
245        pa = pa & ~(ALIGNMENT-1);
246        FLAG = (pa < (thread->mem_access[slot].paddr+LENGTH));
247     },
248    ()
249)
250DEF_MACRO(COUNT_OUT_OF_BOUNDS,
251     {
252        if (!FLAG)
253        {
254               THREAD2STRUCT->vtcm_log.oob_access += SIZE;
255               warn("Scatter/Gather out of bounds of region");
256        }
257     },
258    ()
259)
260
261DEF_MACRO(fLOG_SCATTER_OP,
262    {
263        // Log the size and indicate that the extension ext.c file needs to increment right before memory write
264        THREAD2STRUCT->vtcm_log.op = 1;
265        THREAD2STRUCT->vtcm_log.op_size = SIZE;
266    },
267    ()
268)
269
270
271
272DEF_MACRO(fVLOG_VTCM_WORD_INCREMENT,
273    {
274        int slot = insn->slot;
275        int log_bank = 0;
276        int log_byte =0;
277        paddr_t pa = thread->mem_access[slot].paddr+(OFFSET & ~(ALIGNMENT-1));
278        paddr_t pa_high = thread->mem_access[slot].paddr+LEN;
279        for(int i0 = 0; i0 < 4; i0++)
280        {
281            log_byte =  ((OFFSET>=0)&&((pa+i0)<=pa_high));
282            log_bank |= (log_byte<<i0);
283            LOG_VTCM_BYTE(pa+i0,log_byte,INC.ub[4*IDX+i0],4*IDX+i0);
284        }
285        { LOG_VTCM_BANK(pa, log_bank, IDX); }
286    },
287    ()
288)
289
290DEF_MACRO(fVLOG_VTCM_HALFWORD_INCREMENT,
291    {
292        int slot = insn->slot;
293        int log_bank = 0;
294        int log_byte = 0;
295        paddr_t pa = thread->mem_access[slot].paddr+(OFFSET & ~(ALIGNMENT-1));
296        paddr_t pa_high = thread->mem_access[slot].paddr+LEN;
297        for(int i0 = 0; i0 < 2; i0++) {
298            log_byte =  ((OFFSET>=0)&&((pa+i0)<=pa_high));
299            log_bank |= (log_byte<<i0);
300            LOG_VTCM_BYTE(pa+i0,log_byte,INC.ub[2*IDX+i0],2*IDX+i0);
301        }
302        { LOG_VTCM_BANK(pa, log_bank,IDX); }
303    },
304    ()
305)
306
307DEF_MACRO(fVLOG_VTCM_HALFWORD_INCREMENT_DV,
308    {
309        int slot = insn->slot;
310        int log_bank = 0;
311        int log_byte = 0;
312        paddr_t pa = thread->mem_access[slot].paddr+(OFFSET & ~(ALIGNMENT-1));
313        paddr_t pa_high = thread->mem_access[slot].paddr+LEN;
314        for(int i0 = 0; i0 < 2; i0++) {
315            log_byte =  ((OFFSET>=0)&&((pa+i0)<=pa_high));
316            log_bank |= (log_byte<<i0);
317            LOG_VTCM_BYTE(pa+i0,log_byte,INC.ub[2*IDX+i0],2*IDX+i0);
318        }
319        { LOG_VTCM_BANK(pa, log_bank,(2*IDX2+IDX_H));}
320    },
321    ()
322)
323
324
325
326DEF_MACRO(GATHER_FUNCTION,
327{
328        int slot = insn->slot;
329        int i0;
330        paddr_t pa = thread->mem_access[slot].paddr+OFFSET;
331        paddr_t pa_high = thread->mem_access[slot].paddr+LEN;
332        int log_bank = 0;
333        int log_byte = 0;
334        for(i0 = 0; i0 < ELEMENT_SIZE; i0++)
335        {
336            log_byte =  ((OFFSET>=0)&&((pa+i0)<=pa_high)) && QVAL;
337            log_bank |= (log_byte<<i0);
338            size1u_t B  = sim_mem_read1(thread->system_ptr, thread->threadId, thread->mem_access[slot].paddr+OFFSET+i0);
339            THREAD2STRUCT->tmp_VRegs[0].ub[ELEMENT_SIZE*IDX+i0] = B;
340            LOG_VTCM_BYTE(pa+i0,log_byte,B,ELEMENT_SIZE*IDX+i0);
341        }
342        LOG_VTCM_BANK(pa, log_bank,BANK_IDX);
343},
344()
345)
346
347
348
349DEF_MACRO(fVLOG_VTCM_GATHER_WORD,
350    {
351		GATHER_FUNCTION(EA,OFFSET,IDX, LEN, 4, IDX, 1);
352    },
353    ()
354)
355DEF_MACRO(fVLOG_VTCM_GATHER_HALFWORD,
356    {
357		GATHER_FUNCTION(EA,OFFSET,IDX, LEN, 2, IDX, 1);
358    },
359    ()
360)
361DEF_MACRO(fVLOG_VTCM_GATHER_HALFWORD_DV,
362    {
363		GATHER_FUNCTION(EA,OFFSET,IDX, LEN, 2, (2*IDX2+IDX_H), 1);
364    },
365    ()
366)
367DEF_MACRO(fVLOG_VTCM_GATHER_WORDQ,
368    {
369		GATHER_FUNCTION(EA,OFFSET,IDX, LEN, 4, IDX, fGETQBIT(QsV,4*IDX+i0));
370    },
371    ()
372)
373DEF_MACRO(fVLOG_VTCM_GATHER_HALFWORDQ,
374    {
375		GATHER_FUNCTION(EA,OFFSET,IDX, LEN, 2, IDX, fGETQBIT(QsV,2*IDX+i0));
376    },
377    ()
378)
379
380DEF_MACRO(fVLOG_VTCM_GATHER_HALFWORDQ_DV,
381    {
382		GATHER_FUNCTION(EA,OFFSET,IDX, LEN, 2, (2*IDX2+IDX_H), fGETQBIT(QsV,2*IDX+i0));
383    },
384    ()
385)
386
387
388DEF_MACRO(DEBUG_LOG_ADDR,
389    {
390
391        if (thread->processor_ptr->arch_proc_options->mmvec_network_addr_log2)
392        {
393
394            int slot = insn->slot;
395            paddr_t pa = thread->mem_access[slot].paddr+OFFSET;
396        }
397    },
398    ()
399)
400
401
402
403
404
405
406
407DEF_MACRO(SCATTER_OP_WRITE_TO_MEM,
408    {
409        for (int i = 0; i < mmvecx->vtcm_log.size; i+=sizeof(TYPE))
410        {
411            if ( mmvecx->vtcm_log.mask.ub[i] != 0) {
412                TYPE dst = 0;
413                TYPE inc = 0;
414                for(int j = 0; j < sizeof(TYPE); j++) {
415                    dst |= (sim_mem_read1(thread->system_ptr, thread->threadId, mmvecx->vtcm_log.pa[i+j]) << (8*j));
416                    inc |= mmvecx->vtcm_log.data.ub[j+i] << (8*j);
417
418                    mmvecx->vtcm_log.mask.ub[j+i] = 0;
419                    mmvecx->vtcm_log.data.ub[j+i] = 0;
420                    mmvecx->vtcm_log.offsets.ub[j+i] = 0;
421                }
422                dst += inc;
423                for(int j = 0; j < sizeof(TYPE); j++) {
424                    sim_mem_write1(thread->system_ptr,thread->threadId, mmvecx->vtcm_log.pa[i+j], (dst >> (8*j))& 0xFF );
425                }
426        }
427
428    }
429    },
430    ()
431)
432
433DEF_MACRO(SCATTER_FUNCTION,
434{
435        int slot = insn->slot;
436        int i0;
437        paddr_t pa = thread->mem_access[slot].paddr+OFFSET;
438        paddr_t pa_high = thread->mem_access[slot].paddr+LEN;
439        int log_bank = 0;
440        int log_byte = 0;
441        for(i0 = 0; i0 < ELEMENT_SIZE; i0++) {
442            log_byte = ((OFFSET>=0)&&((pa+i0)<=pa_high)) && QVAL;
443            log_bank |= (log_byte<<i0);
444            LOG_VTCM_BYTE(pa+i0,log_byte,IN.ub[ELEMENT_SIZE*IDX+i0],ELEMENT_SIZE*IDX+i0);
445        }
446        LOG_VTCM_BANK(pa, log_bank,BANK_IDX);
447
448},
449()
450)
451
452DEF_MACRO(fVLOG_VTCM_HALFWORD,
453    {
454		SCATTER_FUNCTION (EA,OFFSET,IDX, LEN, 2, IDX, 1, IN);
455    },
456    ()
457)
458DEF_MACRO(fVLOG_VTCM_WORD,
459    {
460		SCATTER_FUNCTION (EA,OFFSET,IDX, LEN, 4, IDX, 1, IN);
461    },
462    ()
463)
464
465DEF_MACRO(fVLOG_VTCM_HALFWORDQ,
466    {
467		SCATTER_FUNCTION (EA,OFFSET,IDX, LEN, 2, IDX, fGETQBIT(QsV,2*IDX+i0), IN);
468    },
469    ()
470)
471DEF_MACRO(fVLOG_VTCM_WORDQ,
472    {
473		SCATTER_FUNCTION (EA,OFFSET,IDX, LEN, 4, IDX, fGETQBIT(QsV,4*IDX+i0), IN);
474    },
475    ()
476)
477
478
479
480
481
482DEF_MACRO(fVLOG_VTCM_HALFWORD_DV,
483    {
484		SCATTER_FUNCTION (EA,OFFSET,IDX, LEN, 2, (2*IDX2+IDX_H), 1, IN);
485    },
486    ()
487)
488
489DEF_MACRO(fVLOG_VTCM_HALFWORDQ_DV,
490    {
491		SCATTER_FUNCTION (EA,OFFSET,IDX, LEN, 2, (2*IDX2+IDX_H), fGETQBIT(QsV,2*IDX+i0), IN);
492    },
493    ()
494)
495
496
497
498
499
500
501DEF_MACRO(fSTORERELEASE,
502    {
503        fV_AL_CHECK(EA,fVECSIZE()-1);
504
505        mem_store_release(thread, insn, fVECSIZE(), EA&~(fVECSIZE()-1), EA, TYPE, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
506    },
507	(A_STORE,A_MEMLIKE)
508)
509
510DEF_MACRO(fVFETCH_AL,
511    {
512    fV_AL_CHECK(EA,fVECSIZE()-1);
513    mem_fetch_vector(thread, insn, EA&~(fVECSIZE()-1), insn->slot, fVECSIZE());
514    },
515    (A_LOAD,A_MEMLIKE)
516)
517
518
519DEF_MACRO(fLOADMMV_AL,
520    {
521    fV_AL_CHECK(EA,ALIGNMENT-1);
522	thread->last_pkt->double_access_vec = 0;
523    mem_load_vector_oddva(thread, insn, EA&~(ALIGNMENT-1), EA, insn->slot, LEN, &DST.ub[0], LEN, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
524    },
525    (A_LOAD,A_MEMLIKE)
526)
527
528DEF_MACRO(fLOADMMV,
529	fLOADMMV_AL(EA,fVECSIZE(),fVECSIZE(),DST),
530	()
531)
532
533DEF_MACRO(fLOADMMVQ,
534	do {
535		int __i;
536		fLOADMMV_AL(EA,fVECSIZE(),fVECSIZE(),DST);
537		fVFOREACH(8,__i) if (!fGETQBIT(QVAL,__i)) DST.b[__i] = 0;
538	} while (0),
539	()
540)
541
542DEF_MACRO(fLOADMMVNQ,
543	do {
544		int __i;
545		fLOADMMV_AL(EA,fVECSIZE(),fVECSIZE(),DST);
546		fVFOREACH(8,__i) if (fGETQBIT(QVAL,__i)) DST.b[__i] = 0;
547	} while (0),
548	()
549)
550
551DEF_MACRO(fLOADMMVU_AL,
552    {
553    size4u_t size2 = (EA)&(ALIGNMENT-1);
554    size4u_t size1 = LEN-size2;
555	thread->last_pkt->double_access_vec = 1;
556    mem_load_vector_oddva(thread, insn, EA+size1, EA+fVECSIZE(), /* slot */ 1, size2, &DST.ub[size1], size2, fUSE_LOOKUP_ADDRESS());
557    mem_load_vector_oddva(thread, insn, EA, EA,/* slot */ 0, size1, &DST.ub[0], size1, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
558    },
559    (A_LOAD,A_MEMLIKE)
560)
561
562DEF_MACRO(fLOADMMVU,
563	{
564		/* if address happens to be aligned, only do aligned load */
565        thread->last_pkt->pkt_has_vtcm_access = 0;
566        thread->last_pkt->pkt_access_count = 0;
567		if ( (EA & (fVECSIZE()-1)) == 0) {
568            thread->last_pkt->pkt_has_vmemu_access = 0;
569			thread->last_pkt->double_access = 0;
570
571			fLOADMMV_AL(EA,fVECSIZE(),fVECSIZE(),DST);
572		} else {
573            thread->last_pkt->pkt_has_vmemu_access = 1;
574			thread->last_pkt->double_access = 1;
575
576			fLOADMMVU_AL(EA,fVECSIZE(),fVECSIZE(),DST);
577		}
578	},
579	()
580)
581
582DEF_MACRO(fSTOREMMV_AL,
583    {
584    fV_AL_CHECK(EA,ALIGNMENT-1);
585    mem_store_vector_oddva(thread, insn, EA&~(ALIGNMENT-1), EA, insn->slot, LEN, &SRC.ub[0], 0, 0, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
586    },
587    (A_STORE,A_MEMLIKE)
588)
589
590DEF_MACRO(fSTOREMMV,
591	fSTOREMMV_AL(EA,fVECSIZE(),fVECSIZE(),SRC),
592	()
593)
594
595DEF_MACRO(fSTOREMMVQ_AL,
596    do {
597	mmvector_t maskvec;
598	int i;
599	for (i = 0; i < fVECSIZE(); i++) maskvec.ub[i] = fGETQBIT(MASK,i);
600	mem_store_vector_oddva(thread, insn, EA&~(ALIGNMENT-1), EA, insn->slot, LEN, &SRC.ub[0], &maskvec.ub[0], 0, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
601    } while (0),
602    (A_STORE,A_MEMLIKE)
603)
604
605DEF_MACRO(fSTOREMMVQ,
606	fSTOREMMVQ_AL(EA,fVECSIZE(),fVECSIZE(),SRC,MASK),
607	()
608)
609
610DEF_MACRO(fSTOREMMVNQ_AL,
611    {
612	mmvector_t maskvec;
613	int i;
614	for (i = 0; i < fVECSIZE(); i++) maskvec.ub[i] = fGETQBIT(MASK,i);
615        fV_AL_CHECK(EA,ALIGNMENT-1);
616	mem_store_vector_oddva(thread, insn, EA&~(ALIGNMENT-1), EA, insn->slot, LEN, &SRC.ub[0], &maskvec.ub[0], 1, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
617    },
618    (A_STORE,A_MEMLIKE)
619)
620
621DEF_MACRO(fSTOREMMVNQ,
622	fSTOREMMVNQ_AL(EA,fVECSIZE(),fVECSIZE(),SRC,MASK),
623	()
624)
625
626DEF_MACRO(fSTOREMMVU_AL,
627    {
628    size4u_t size1 = ALIGNMENT-((EA)&(ALIGNMENT-1));
629    size4u_t size2;
630    if (size1>LEN) size1 = LEN;
631    size2 = LEN-size1;
632    mem_store_vector_oddva(thread, insn, EA+size1, EA+fVECSIZE(), /* slot */ 1, size2, &SRC.ub[size1], 0, 0, fUSE_LOOKUP_ADDRESS());
633    mem_store_vector_oddva(thread, insn, EA, EA, /* slot */ 0, size1, &SRC.ub[0], 0, 0, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
634    },
635    (A_STORE,A_MEMLIKE)
636)
637
638DEF_MACRO(fSTOREMMVU,
639	{
640        thread->last_pkt->pkt_has_vtcm_access = 0;
641        thread->last_pkt->pkt_access_count = 0;
642		if ( (EA & (fVECSIZE()-1)) == 0) {
643			thread->last_pkt->double_access = 0;
644			fSTOREMMV_AL(EA,fVECSIZE(),fVECSIZE(),SRC);
645		} else {
646			thread->last_pkt->double_access = 1;
647            thread->last_pkt->pkt_has_vmemu_access = 1;
648			fSTOREMMVU_AL(EA,fVECSIZE(),fVECSIZE(),SRC);
649		}
650	},
651	()
652)
653
654DEF_MACRO(fSTOREMMVQU_AL,
655    {
656	size4u_t size1 = ALIGNMENT-((EA)&(ALIGNMENT-1));
657	size4u_t size2;
658	mmvector_t maskvec;
659	int i;
660	for (i = 0; i < fVECSIZE(); i++) maskvec.ub[i] = fGETQBIT(MASK,i);
661	if (size1>LEN) size1 = LEN;
662	size2 = LEN-size1;
663	mem_store_vector_oddva(thread, insn, EA+size1, EA+fVECSIZE(),/* slot */ 1, size2, &SRC.ub[size1], &maskvec.ub[size1], 0, fUSE_LOOKUP_ADDRESS());
664	mem_store_vector_oddva(thread, insn, EA, /* slot */ 0, size1, &SRC.ub[0], &maskvec.ub[0], 0, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
665    },
666    (A_STORE,A_MEMLIKE)
667)
668
669DEF_MACRO(fSTOREMMVQU,
670	{
671        thread->last_pkt->pkt_has_vtcm_access = 0;
672        thread->last_pkt->pkt_access_count = 0;
673		if ( (EA & (fVECSIZE()-1)) == 0) {
674			thread->last_pkt->double_access = 0;
675			fSTOREMMVQ_AL(EA,fVECSIZE(),fVECSIZE(),SRC,MASK);
676		} else {
677			thread->last_pkt->double_access = 1;
678            thread->last_pkt->pkt_has_vmemu_access = 1;
679			fSTOREMMVQU_AL(EA,fVECSIZE(),fVECSIZE(),SRC,MASK);
680		}
681	},
682	()
683)
684
685DEF_MACRO(fSTOREMMVNQU_AL,
686    {
687	size4u_t size1 = ALIGNMENT-((EA)&(ALIGNMENT-1));
688	size4u_t size2;
689	mmvector_t maskvec;
690	int i;
691	for (i = 0; i < fVECSIZE(); i++) maskvec.ub[i] = fGETQBIT(MASK,i);
692	if (size1>LEN) size1 = LEN;
693	size2 = LEN-size1;
694	mem_store_vector_oddva(thread, insn, EA+size1, EA+fVECSIZE(), /* slot */ 1, size2, &SRC.ub[size1], &maskvec.ub[size1], 1, fUSE_LOOKUP_ADDRESS());
695	mem_store_vector_oddva(thread, insn, EA, EA, /* slot */ 0, size1, &SRC.ub[0], &maskvec.ub[0], 1, fUSE_LOOKUP_ADDRESS_BY_REV(thread->processor_ptr));
696    },
697    (A_STORE,A_MEMLIKE)
698)
699
700DEF_MACRO(fSTOREMMVNQU,
701	{
702        thread->last_pkt->pkt_has_vtcm_access = 0;
703        thread->last_pkt->pkt_access_count = 0;
704		if ( (EA & (fVECSIZE()-1)) == 0) {
705			thread->last_pkt->double_access = 0;
706			fSTOREMMVNQ_AL(EA,fVECSIZE(),fVECSIZE(),SRC,MASK);
707		} else {
708			thread->last_pkt->double_access = 1;
709            thread->last_pkt->pkt_has_vmemu_access = 1;
710			fSTOREMMVNQU_AL(EA,fVECSIZE(),fVECSIZE(),SRC,MASK);
711		}
712	},
713	()
714)
715
716
717
718
719DEF_MACRO(fVFOREACH,
720    for (VAR = 0; VAR < fVELEM(WIDTH); VAR++),
721    /* NOTHING */
722)
723
724DEF_MACRO(fVARRAY_ELEMENT_ACCESS,
725    ARRAY.v[(INDEX) / (fVECSIZE()/(sizeof(ARRAY.TYPE[0])))].TYPE[(INDEX) % (fVECSIZE()/(sizeof(ARRAY.TYPE[0])))],
726    ()
727)
728
729DEF_MACRO(fVNEWCANCEL,
730	do { THREAD2STRUCT->VRegs_select &= ~(1<<(REGNUM)); } while (0),
731	()
732)
733
734DEF_MACRO(fTMPVDATA,
735	mmvec_vtmp_data(thread),
736	(A_CVI)
737)
738
739DEF_MACRO(fVSATDW,
740    fVSATW( ( ( ((long long)U)<<32 ) | fZXTN(32,64,V) ) ),
741    /* attribs */
742)
743
744DEF_MACRO(fVASL_SATHI,
745    fVSATW(((U)<<1) | ((V)>>31)),
746    /* attribs */
747)
748
749DEF_MACRO(fVUADDSAT,
750	fVSATUN( WIDTH, fZXTN(WIDTH, 2*WIDTH, U)  + fZXTN(WIDTH, 2*WIDTH, V)),
751	/* attribs */
752)
753
754DEF_MACRO(fVSADDSAT,
755	fVSATN(  WIDTH, fSXTN(WIDTH, 2*WIDTH, U)  + fSXTN(WIDTH, 2*WIDTH, V)),
756	/* attribs */
757)
758
759DEF_MACRO(fVUSUBSAT,
760	fVSATUN( WIDTH, fZXTN(WIDTH, 2*WIDTH, U)  - fZXTN(WIDTH, 2*WIDTH, V)),
761	/* attribs */
762)
763
764DEF_MACRO(fVSSUBSAT,
765	fVSATN(  WIDTH, fSXTN(WIDTH, 2*WIDTH, U)  - fSXTN(WIDTH, 2*WIDTH, V)),
766	/* attribs */
767)
768
769DEF_MACRO(fVAVGU,
770	((fZXTN(WIDTH, 2*WIDTH, U) + fZXTN(WIDTH, 2*WIDTH, V))>>1),
771	/* attribs */
772)
773
774DEF_MACRO(fVAVGURND,
775	((fZXTN(WIDTH, 2*WIDTH, U) + fZXTN(WIDTH, 2*WIDTH, V)+1)>>1),
776	/* attribs */
777)
778
779DEF_MACRO(fVNAVGU,
780	((fZXTN(WIDTH, 2*WIDTH, U) - fZXTN(WIDTH, 2*WIDTH, V))>>1),
781	/* attribs */
782)
783
784DEF_MACRO(fVNAVGURNDSAT,
785	fVSATUN(WIDTH,((fZXTN(WIDTH, 2*WIDTH, U) - fZXTN(WIDTH, 2*WIDTH, V)+1)>>1)),
786	/* attribs */
787)
788
789DEF_MACRO(fVAVGS,
790	((fSXTN(WIDTH, 2*WIDTH, U) + fSXTN(WIDTH, 2*WIDTH, V))>>1),
791	/* attribs */
792)
793
794DEF_MACRO(fVAVGSRND,
795	((fSXTN(WIDTH, 2*WIDTH, U) + fSXTN(WIDTH, 2*WIDTH, V)+1)>>1),
796	/* attribs */
797)
798
799DEF_MACRO(fVNAVGS,
800	((fSXTN(WIDTH, 2*WIDTH, U) - fSXTN(WIDTH, 2*WIDTH, V))>>1),
801	/* attribs */
802)
803
804DEF_MACRO(fVNAVGSRND,
805	((fSXTN(WIDTH, 2*WIDTH, U) - fSXTN(WIDTH, 2*WIDTH, V)+1)>>1),
806	/* attribs */
807)
808
809DEF_MACRO(fVNAVGSRNDSAT,
810	fVSATN(WIDTH,((fSXTN(WIDTH, 2*WIDTH, U) - fSXTN(WIDTH, 2*WIDTH, V)+1)>>1)),
811	/* attribs */
812)
813
814
815DEF_MACRO(fVNOROUND,
816	VAL,
817	/* NOTHING */
818)
819DEF_MACRO(fVNOSAT,
820	VAL,
821	/* NOTHING */
822)
823
824DEF_MACRO(fVROUND,
825	((VAL) + (((SHAMT)>0)?(1LL<<((SHAMT)-1)):0)),
826	/* NOTHING */
827)
828
829DEF_MACRO(fCARRY_FROM_ADD32,
830	(((fZXTN(32,64,A)+fZXTN(32,64,B)+C) >> 32) & 1),
831	/* NOTHING */
832)
833
834DEF_MACRO(fUARCH_NOTE_PUMP_4X,
835	,
836	()
837)
838
839DEF_MACRO(fUARCH_NOTE_PUMP_2X,
840	,
841	()
842)
843