|
|
1.1 root 1: #! /bin/sh
2:
3: # $Id: sparc-insns-auto.sh,v 1.5 2007/03/29 01:16:09 fredette Exp $
4:
5: # ic/sparc/sparc-insns-auto.sh - automatically generates C code
6: # for many SPARC emulation instructions:
7:
8: #
9: # Copyright (c) 2005 Matt Fredette
10: # All rights reserved.
11: #
12: # Redistribution and use in source and binary forms, with or without
13: # modification, are permitted provided that the following conditions
14: # are met:
15: # 1. Redistributions of source code must retain the above copyright
16: # notice, this list of conditions and the following disclaimer.
17: # 2. Redistributions in binary form must reproduce the above copyright
18: # notice, this list of conditions and the following disclaimer in the
19: # documentation and/or other materials provided with the distribution.
20: # 3. All advertising materials mentioning features or use of this software
21: # must display the following acknowledgement:
22: # This product includes software developed by Matt Fredette.
23: # 4. The name of the author may not be used to endorse or promote products
24: # derived from this software without specific prior written permission.
25: #
26: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28: # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29: # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30: # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31: # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32: # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34: # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35: # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: # POSSIBILITY OF SUCH DAMAGE.
37: #
38:
39: header=false
40:
41: for option
42: do
43: case $option in
44: --header) header=true ;;
45: esac
46: done
47:
48: PROG=`basename $0`
49: cat <<EOF
50: /* automatically generated by $PROG, do not edit! */
51: _TME_RCSID("\$Id: sparc-insns-auto.sh,v 1.5 2007/03/29 01:16:09 fredette Exp $");
52:
53: EOF
54: if $header; then :; else
55: cat <<EOF
56: #include "sparc-impl.h"
57: EOF
58: fi
59:
60: # permute over architecture:
61: #
62: for arch in 32; do
63:
64: # the sparc64 support depends on a 64-bit integer type:
65: #
66: if test ${arch} = 64; then
67: echo ""
68: echo "#ifdef TME_HAVE_INT64_T"
69: fi
70:
71: # get the name of the register with the integer condition codes, a
72: # shift value for 32-bit registers, and the architecture version:
73: #
74: if test ${arch} = 32; then
75: ccr=32_PSR
76: ccr_ireg='tme_sparc32_ireg_psr'
77: reg32_shift=''
78: version=8
79: else
80: ccr=64_CCR
81: ccr_ireg='tme_sparc64_ireg_ccr'
82: reg32_shift=' << 1'
83: version=9
84: fi
85:
86: # fix the architecture version:
87: #
88: if $header; then :; else
89: echo ""
90: echo "#undef TME_SPARC_VERSION"
91: echo "#define TME_SPARC_VERSION(ic) (${version})"
92: fi
93:
94: # the alternate ASI function:
95: #
96: if $header; then :; else
97: echo "static tme_uint32_t"
98: echo "_tme_sparc${arch}_alternate_asi_mask(struct tme_sparc *ic)"
99: echo "{"
100: echo " unsigned int asi_data;"
101: echo " tme_uint32_t asi_mask_data;"
102: echo ""
103: echo " /* get the ASI, assuming that the i bit is zero: */"
104: echo " asi_data = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, (0xff << 5));"
105: if test ${arch} = 32; then
106: echo ""
107: echo " /* this is a privileged instruction: */"
108: echo " TME_SPARC_INSN_PRIV;"
109: echo ""
110: echo " /* if the i bit is one, this is an illegal instruction: */"
111: echo " if (__tme_predict_false(TME_SPARC_INSN & TME_BIT(13))) {"
112: echo " TME_SPARC_INSN_ILL;"
113: echo " }"
114: echo ""
115: echo " /* map the ASI into an ASI mask: */"
116: echo " switch (asi_data) {"
117: echo " case TME_SPARC32_ASI_UI: asi_mask_data = TME_SPARC32_ASI_MASK_UI; break;"
118: echo " case TME_SPARC32_ASI_UD: asi_mask_data = TME_SPARC32_ASI_MASK_UD; break;"
119: echo " case TME_SPARC32_ASI_SI: asi_mask_data = TME_SPARC32_ASI_MASK_SI; break;"
120: echo " case TME_SPARC32_ASI_SD: asi_mask_data = TME_SPARC32_ASI_MASK_SD; break;"
121: echo " default: asi_mask_data = TME_SPARC_ASI_MASK(asi_data); break;"
122: echo " }"
123: else
124: echo ""
125: echo " /* if the i bit is one, use the address space in the ASI register: */"
126: echo " if (TME_SPARC_INSN & TME_BIT(13)) {"
127: echo " asi_data = ic->tme_sparc_ireg_asi;"
128: echo " }"
129: echo ""
130: echo " /* start the ASI mask: */"
131: echo " asi_mask_data = TME_SPARC_ASI_MASK(asi_data);"
132:
133: echo ""
134: echo " /* if this is an unpriviledged access: */"
135: echo " if (!TME_SPARC_PRIV(ic)) {"
136: echo ""
137: echo " /* this is a priviledge violation if bit 7 of the ASI is zero: */"
138: echo " if (asi_data < 0x80) {"
139: echo " TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_privileged_instruction);"
140: echo " }"
141: echo " }"
142: fi
143: echo ""
144: echo " return (asi_mask_data);"
145: echo "}"
146: fi
147:
148: # permute over instruction:
149: #
150: for insn in \
151: add \
152: addcc \
153: sub \
154: subcc \
155: or \
156: orcc \
157: orn \
158: orncc \
159: and \
160: andcc \
161: andn \
162: andncc \
163: xor \
164: xorcc \
165: xnor \
166: xnorcc \
167: addx \
168: addxcc \
169: subx \
170: subxcc \
171: taddcc taddcctv \
172: tsubcc tsubcctv \
173: umul umulcc smul smulcc \
174: udiv udivcc sdiv sdivcc \
175: sll \
176: srl \
177: sra \
178: ldb stb \
179: ldh sth \
180: ld st \
181: ldd std \
182: ldstub ldstuba swap swapa \
183: ldba stba \
184: ldha stha \
185: lda sta \
186: ldda stda \
187: jmpl \
188: ldf lddf ldfsr \
189: stf stdf stfsr \
190: mulscc \
191: ; do
192:
193: # if we're making the header, just emit declarations:
194: #
195: if $header; then
196: echo "TME_SPARC_FORMAT3_DECL(tme_sparc${arch}_${insn}, tme_uint${arch}_t);"
197: continue
198: fi
199:
200: # an ALU instruction:
201: #
202: case ${insn} in
203: add | sub | or | orn | and | andn | xor | xnor | \
204: addx | subx | umul | smul | udiv | sdiv)
205: cc=false
206: ;;
207: addcc | subcc | orcc | orncc | andcc | andncc | xorcc | xnorcc | \
208: addxcc | subxcc | umulcc | smulcc | udivcc | sdivcc | \
209: taddcc | tsubcc | taddcctv | tsubcctv | \
210: mulscc)
211: cc=true
212: ;;
213: *)
214: cc=
215: ;;
216: esac
217: if test "x${cc}" != x; then
218:
219: # characterize each function:
220: #
221: sign=u ; size_src=${arch} ; size_dst=${arch} ; arith=logical ; with_c= ; tagged=
222: case "${insn}" in
223: add | addcc) op='src1 + src2' ; arith=add ;;
224: sub | subcc) op='src1 - src2' ; arith=sub ;;
225: or | orcc) op='src1 | src2' ;;
226: orn | orncc) op='src1 | ~src2' ;;
227: and | andcc) op='src1 & src2' ;;
228: andn | andncc) op='src1 & ~src2' ;;
229: xor | xorcc) op='src1 ^ src2' ;;
230: xnor | xnorcc) op='src1 ^ ~src2' ;;
231: addx | addxcc) op='src1 + src2' ; arith=add ; with_c=+ ;;
232: subx | subxcc) op='src1 - src2' ; arith=sub ; with_c=- ;;
233: taddcc) op='src1 + src2' ; arith=add ; tagged=x ;;
234: taddcctv) op='src1 + src2' ; arith=add ; tagged=tv ;;
235: tsubcc) op='src1 - src2' ; arith=sub ; tagged=x ;;
236: tsubcctv) op='src1 - src2' ; arith=sub ; tagged=tv ;;
237: umul | umulcc) arith=mul ; size_src=32 ;;
238: smul | smulcc) arith=mul ; size_src=32 ; sign= ;;
239: udiv | udivcc) arith=udiv ; size_src=32 ; size_dst=32 ;;
240: sdiv | sdivcc) arith=sdiv ; size_src=32 ; size_dst=32 ; sign= ;;
241: mulscc) arith=add ; size_src=32 ; size_dst=32 ;;
242: *) echo "$0 internal error: unknown ALU function ${insn}" 1>&2 ; exit 1 ;;
243: esac
244:
245: # open the function:
246: #
247: echo ""
248: echo "/* this does a sparc${arch} \"${insn} SRC1, SRC2, DST\": */"
249: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
250: echo "{"
251:
252: # declare our locals:
253: #
254: echo " tme_${sign}int${size_src}_t src1;"
255: echo " tme_${sign}int${size_src}_t src2;"
256: echo " tme_${sign}int${size_dst}_t dst;"
257: case "${insn}" in
258: umul* | smul* | udiv* | sdiv*)
259: echo " tme_${sign}int64_t val64;"
260: ;;
261: mulscc)
262: echo " tme_uint32_t y;"
263: ;;
264: esac
265: if ${cc}; then
266: echo " tme_uint32_t cc;"
267: fi
268:
269: echo ""
270: echo " /* get the operands: */"
271: echo " src1 = (tme_${sign}int${arch}_t) TME_SPARC_FORMAT3_RS1;"
272: echo " src2 = (tme_${sign}int${arch}_t) TME_SPARC_FORMAT3_RS2;"
273:
274: echo ""
275: echo " /* perform the operation: */"
276: case "${insn}" in
277: umul | umulcc | smul | smulcc)
278: echo " val64 = (((tme_${sign}int64_t) src1) * src2);"
279: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift}) = (((tme_uint64_t) val64) >> 32);"
280: echo " dst = ((tme_${sign}int64_t) val64);"
281: ;;
282: udiv | udivcc | sdiv | sdivcc)
283: echo " val64 = ((((tme_uint64_t) ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift})) << 32) | ((tme_uint32_t) src1));"
284: echo " val64 /= src2;"
285: echo " /* XXX FIXME - overflow handling is missing here: */"
286: echo " dst = val64;"
287: ;;
288: mulscc)
289: echo ""
290: echo " /* \"(1) The multiplier is established as r[rs2] if the i field is zero, or "
291: echo " sign_ext(simm13) if the i field is one.\""
292: echo ""
293: echo " \"(3) If the least significant bit of the Y register = 1, the shifted"
294: echo " value from step (2) is added to the multiplier. If the LSB of the"
295: echo " Y register = 0, then 0 is added to the shifted value from step (2).\" */"
296: echo " y = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift});"
297: echo " if ((y & 1) == 0) {"
298: echo " src2 = 0;"
299: echo " }"
300: echo ""
301: echo " /* \"(6) The Y register is shifted right by one bit, with the LSB of the"
302: echo " unshifted r[rs1] replacing the MSB of Y.\" */"
303: echo " y >>= 1;"
304: echo " if (src1 & 1) {"
305: echo " y += 0x80000000;"
306: echo " }"
307: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_Y${reg32_shift}) = y;"
308: echo ""
309: echo " /* \"(2) A 32-bit value is computed by shifting r[rs1] right by one"
310: echo " bit with (N xor V) from the PSR replacing the high-order bit."
311: echo " (This is the proper sign for the previous partial product.)\" */"
312: echo " src1 >>= 1;"
313: echo " if (((ic->${ccr_ireg} ^ (ic->${ccr_ireg} * (TME_SPARC${ccr}_ICC_N / TME_SPARC${ccr}_ICC_V))) & TME_SPARC${ccr}_ICC_N) != 0) {"
314: echo " src1 += 0x80000000;"
315: echo " }"
316: echo ""
317: echo " /* \"(4) The sum from step (3) is written into r[rd].\" */"
318: echo " dst = src1 + src2;"
319: echo ""
320: echo " /* \"(5) The integer condition codes, icc, are updated according to the"
321: echo " addition performed in step (3).\" */"
322: ;;
323: *)
324: echo " dst = ${op};"
325: if test "x${with_c}" != x; then
326: echo " dst ${with_c}= ((ic->${ccr_ireg} & TME_SPARC${ccr}_ICC_C) != 0);"
327: fi
328: esac
329:
330: # unless this is a tagged-and-trap-on-overflow operation:
331: #
332: if test "x${tagged}" != xtv; then
333: echo ""
334: echo " /* store the destination: */"
335: echo " TME_SPARC_FORMAT3_RD = (tme_${sign}int${arch}_t) dst;"
336: fi
337:
338: # if this instruction modifies the condition codes:
339: #
340: if ${cc}; then
341:
342: echo ""
343: echo " /* set Z if the destination is zero: */"
344: echo -n " cc = ((dst == 0) * (TME_SPARC${ccr}_ICC_Z"
345: if test ${arch} = 64; then
346: echo -n " + TME_SPARC${ccr}_XCC_Z"
347: fi
348: echo "));"
349:
350: # set the 32-bit, and possibly the 64-bit, condition codes:
351: #
352: arch_cc=16
353: while test `expr ${arch_cc} \< ${arch}` = 1; do
354: arch_cc=`expr ${arch_cc} \* 2`
355:
356: case ${arch_cc} in
357: 32) xcc=ICC ;;
358: 64) xcc=XCC ;;
359: esac
360:
361: if test `expr ${arch_cc} \<= ${size_dst}` = 1 || test "x${sign}" = xs; then
362: echo ""
363: echo " /* set N if the destination is negative: */"
364: echo " cc += ((((tme_int${arch_cc}_t) dst) < 0) * TME_SPARC${ccr}_${xcc}_N);"
365: fi
366:
367: case $arith in
368: add)
369: ones="(((tme_${sign}int${arch_cc}_t) 0) - 1)"
370:
371: echo ""
372: echo " /* if the operands are the same sign, and the destination has"
373: echo " a different sign, set V: */"
374: echo " cc += ((((tme_int${arch_cc}_t) ((src2 ^ dst) & (src1 ^ (src2 ^ ${ones})))) < 0) * TME_SPARC${ccr}_${xcc}_V);"
375:
376: echo ""
377: echo " /* if src1 and src2 both have the high bit set, or if dst does"
378: echo " not have the high bit set and either src1 or src2 does, set C: */"
379: echo " cc += (((tme_int${arch_cc}_t) (((tme_uint${arch_cc}_t) (src1 & src2)) | ((((tme_uint${arch_cc}_t) dst) ^ ${ones}) & ((tme_uint${arch_cc}_t) (src1 | src2))))) < 0) * TME_SPARC${ccr}_${xcc}_C;"
380: ;;
381: sub)
382:
383: echo ""
384: echo " /* if the operands are different signs, and the destination has"
385: echo " a different sign from the first operand, set V: */"
386: echo " cc += ((((tme_int${arch_cc}_t) ((src1 ^ src2) & (src1 ^ dst))) < 0) * TME_SPARC${ccr}_${xcc}_V);"
387:
388: echo ""
389: echo " /* if src2 is greater than src1, set C: */"
390: echo -n " cc += ((((tme_uint${arch_cc}_t) src2) > ((tme_uint${arch_cc}_t) src1))"
391: if test "x${with_c}" != x; then
392: echo -n " || (((tme_uint${arch_cc}_t) src2) == ((tme_uint${arch_cc}_t) src1) && (ic->${ccr_ireg} & TME_SPARC${ccr}_ICC_C))"
393: fi
394: echo ") * TME_SPARC${ccr}_${xcc}_C;"
395: ;;
396: logical | mul)
397: ;;
398: udiv)
399: ;;
400: sdiv)
401: ;;
402: *) echo "$0 internal error: unknown arithmetic type ${arith}" 1>&2 ; exit 1 ;;
403: esac
404: done
405:
406: # if this is a tagged operation:
407: #
408: if test "x${tagged}" != x; then
409:
410: echo ""
411: echo " /* set V if bits zero or one of src1 or src2 are set: */"
412: echo " cc |= ((((src1 | src2) & 3) != 0) * TME_SPARC${ccr}_ICC_V);"
413:
414: # if this is a tagged-and-trap-on-overflow operation:
415: #
416: if test "x${tagged}" = xtv; then
417:
418: echo ""
419: echo " /* trap on a tagged overflow: */"
420: echo " if (cc & TME_SPARC${ccr}_ICC_V) {"
421: echo " tme_sparc${arch}_trap(ic, TME_SPARC_TRAP_tag_overflow);"
422: echo " }"
423:
424: echo " /* store the destination: */"
425: echo " TME_SPARC_FORMAT3_RD = (tme_${sign}int${arch}_t) dst;"
426: fi
427: fi
428:
429: echo ""
430: echo " /* set the condition codes: */"
431: echo -n " ic->${ccr_ireg} = "
432: if test ${arch} = 32; then
433: echo -n "(ic->${ccr_ireg} & ~TME_SPARC32_PSR_ICC) | "
434: fi
435: echo "cc;"
436: fi
437:
438: echo ""
439: echo " TME_SPARC_INSN_OK;"
440: echo "}"
441: fi
442:
443: # a shift instruction:
444: #
445: case ${insn} in
446: sll | srl | sra)
447:
448: # get the sign of this shift:
449: #
450: if test ${insn} = sra; then sign= ; else sign=u; fi
451:
452: echo ""
453: echo "/* the sparc${arch} ${insn} function: */"
454: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
455: echo "{"
456: echo " tme_${sign}int${arch}_t dst;"
457: echo " unsigned int count;"
458: echo ""
459: echo " /* get the value and the shift count: */"
460: echo " dst = TME_SPARC_FORMAT3_RS1;"
461: echo " count = TME_SPARC_FORMAT3_RS2;"
462:
463: # if we're on sparc64:
464: #
465: if test ${arch} = 64; then
466:
467: echo ""
468: echo " /* if the X bit is clear: */"
469: echo " if ((TME_SPARC_INSN & TME_BIT(12)) == 0) {"
470: echo ""
471: echo " /* limit the count: */"
472: echo " count %= 32;"
473: if test ${insn} != sll; then
474: echo ""
475: echo " /* clip the value to 32 bits: */"
476: echo " dst = (tme_${sign}int32_t) dst;"
477: fi
478: echo " }"
479: fi
480:
481: echo ""
482: echo " /* limit the count: */"
483: echo " count %= ${arch};"
484: echo ""
485: echo " /* do the shift: */"
486: if test "${insn}" = sra; then
487: echo "#ifdef SHIFTSIGNED_INT${arch}_T"
488: fi
489: echo "#if (SHIFTMAX_INT${arch}_T < (${arch} - 1))"
490: echo "#error \"cannot do full shifts of a tme_int${arch}_t\""
491: echo "#endif /* (SHIFTMAX_INT${arch}_T < (${arch} - 1)) */"
492: if test ${insn} = sll; then
493: echo " dst <<= count;"
494: else
495: echo " dst >>= count;"
496: fi
497: if test "${insn}" = sra; then
498: echo "#else /* !SHIFTSIGNED_INT${arch}_T */"
499: echo " for (; count-- > 0; ) {"
500: echo " dst = (dst & ~((tme_${sign}int${arch}_t) 1)) / 2;"
501: echo " }"
502: echo "#endif /* !SHIFTSIGNED_INT${arch}_T */"
503: fi
504:
505: echo ""
506: echo " /* store the destination: */"
507: echo " TME_SPARC_FORMAT3_RD = dst;"
508: echo ""
509: echo " TME_SPARC_INSN_OK;"
510: echo "}"
511: ;;
512: esac
513:
514: # a load or store instruction:
515: #
516: size=
517: case "${insn}" in
518: ldb | stb | ldstub | ldba | stba | ldstuba) size=8 ;;
519: ldh | sth | ldha | stha) size=16 ;;
520: ld | st | swap | lda | sta | swapa) size=32 ;;
521: ldd | std | ldda | stda) size=32 ;;
522: esac
523: if test "x${size}" != x; then
524:
525: # set the alternate space indication:
526: #
527: case "${insn}" in
528: *a) alternate=true ;;
529: *) alternate=false ;;
530: esac
531:
532: # set the atomic and double indications:
533: #
534: atomic=false
535: double=false
536: case "${insn}" in
537: ldstub | ldstuba | swap | swapa) atomic=true ;;
538: ldd* | std*) double=true ; size=64 ;;
539: esac
540:
541: # if this is only a load, we are reading, otherwise we are writing:
542: #
543: cycle=write
544: capcycle=WRITE
545: slow=store
546: case "${insn}" in
547: ldstub*) ;;
548: ld*)
549: cycle=read
550: capcycle=READ
551: slow=load
552: ;;
553: esac
554:
555: # start the instruction:
556: #
557: echo ""
558: echo "/* this does a sparc${arch} ${insn}: */"
559: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
560: echo "{"
561:
562: # our locals:
563: #
564: if ${alternate}; then
565: echo " tme_uint32_t asi_mask_data;"
566: asi_mask_data=asi_mask_data
567: else
568: asi_mask_data="ic->tme_sparc_asi_mask_data"
569: fi
570: echo " tme_uint${arch}_t address;"
571: echo " struct tme_sparc_tlb *dtlb;"
572: echo -n " "
573: if test ${slow} = load; then echo -n "const "; fi
574: echo "tme_shared tme_uint8_t *memory;"
575: echo " tme_uint${arch}_t value;"
576:
577: if ${alternate}; then
578: echo ""
579: echo " /* get the alternate ASI mask: */"
580: echo " asi_mask_data = _tme_sparc${arch}_alternate_asi_mask(ic);"
581: fi
582:
583: echo ""
584: echo " /* get the address: */"
585: echo " address = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;"
586:
587: echo ""
588: echo "#ifdef _TME_SPARC_STATS"
589: echo " /* track statistics: */"
590: echo " ic->tme_sparc_stats.tme_sparc_stats_memory_total++;"
591: echo "#endif /* _TME_SPARC_STATS */"
592:
593: # if this is some kind of a store, except for an ldstub:
594: #
595: case "${insn}" in
596: std*)
597: echo ""
598: echo " /* log the values stored: */"
599: # XXX FIXME - we can't verify a std yet:
600: #
601: echo " tme_sparc_log(ic, 1000, TME_OK, "
602: echo " (TME_SPARC_LOG_HANDLE(ic),"
603: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%08x 0x%08x\"),"
604: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data}),"
605: echo " address,"
606: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD,"
607: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD_ODD));"
608: ;;
609: st* | swap*)
610: echo ""
611: echo " /* log the value stored: */"
612: echo " tme_sparc_verify_mem${size}(ic, ${asi_mask_data}, address, (tme_uint${size}_t) TME_SPARC_FORMAT3_RD, TME_BUS_CYCLE_WRITE);"
613: echo " tme_sparc_log(ic, 1000, TME_OK, "
614: echo " (TME_SPARC_LOG_HANDLE(ic),"
615: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%0"`expr ${size} / 4`"x\"),"
616: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data}),"
617: echo " address,"
618: echo " (tme_uint${size}_t) TME_SPARC_FORMAT3_RD));"
619: ;;
620: esac
621:
622: echo ""
623: echo " /* get and busy the DTLB entry: */"
624: echo " dtlb = TME_SPARC_DTLB_ENTRY(ic, address);"
625: echo " tme_sparc_tlb_busy(dtlb);"
626:
627: echo ""
628: echo " /* assume that this DTLB applies and allows fast transfers: */"
629: echo " memory = dtlb->tme_sparc_tlb_emulator_off_${cycle};"
630:
631: echo ""
632: echo " /* we must call the slow ${slow} function if: */"
633: echo " if (__tme_predict_false("
634: echo ""
635: echo " /* the DTLB entry is invalid: */"
636: echo " tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb)"
637: echo ""
638: echo " /* the DTLB entry does not cover the needed addresses: */"
639: echo " || (dtlb->tme_sparc_tlb_addr_first > address)"
640: echo " || (dtlb->tme_sparc_tlb_addr_last < (address + ((${size} / 8) - 1)))"
641: echo ""
642: echo " /* the DTLB entry does not cover the needed address space: */"
643: echo " || (!TME_SPARC_TLB_ASI_MASK_OK(dtlb, ${asi_mask_data}))"
644: echo ""
645: echo " /* the DTLB entry does not allow fast transfers: */"
646: if $atomic; then
647: echo " || (memory != dtlb->tme_sparc_tlb_emulator_off_read)"
648: fi
649: echo " || (memory == TME_EMULATOR_OFF_UNDEF)"
650: if test ${size} != 8; then
651: echo ""
652: echo " /* the address is misaligned: */"
653: echo " || ((address % (${size} / 8)) != 0)"
654: fi
655: if ${double}; then
656: echo ""
657: echo " /* the destination register number is odd: */"
658: echo " || ((TME_SPARC_INSN & TME_BIT(25)) != 0)"
659: fi
660: echo ""
661: echo " )) {"
662:
663: echo ""
664: echo " /* call the slow ${slow} function: */"
665: echo " memory = tme_sparc${arch}_${slow}(ic,"
666: echo " address,"
667: if test ${slow} = store; then
668: echo " &TME_SPARC_FORMAT3_RD,"
669: fi
670: echo -n " ("
671: if ${atomic}; then
672: echo "TME_SPARC_SLOW_FLAG_ATOMIC"
673: echo -n " | "
674: fi
675: if ${alternate}; then
676: echo "TME_SPARC_SLOW_FLAG_A"
677: echo -n " | "
678: fi
679: echo "(${size} / 8)));"
680:
681: if test ${slow} = store; then
682: echo ""
683: echo " /* if the slow ${slow} function did the transfer, return now: */"
684: echo " if (__tme_predict_false(memory == TME_EMULATOR_OFF_UNDEF)) {"
685: echo " tme_sparc_tlb_unbusy(dtlb);"
686: echo " TME_SPARC_INSN_OK;"
687: echo " }"
688: fi
689: echo " }"
690:
691: echo ""
692: echo " /* do the fast transfer: */"
693: echo " memory += address;"
694:
695: # dispatch on the instruction:
696: #
697: case "${insn}" in
698: ldd*)
699: if test ${arch} = 32; then
700: echo " value = tme_memory_bus_read32(((const tme_shared tme_uint32_t *) memory) + 0, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 2, sizeof(tme_uint${arch}_t));"
701: echo " TME_SPARC_FORMAT3_RD = tme_betoh_u32(value);"
702: echo " value = tme_memory_bus_read32(((const tme_shared tme_uint32_t *) memory) + 1, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t), sizeof(tme_uint${arch}_t));"
703: echo " TME_SPARC_FORMAT3_RD_ODD = tme_betoh_u32(value);"
704: else
705: echo "$PROG fatal: need ${insn} support for sparc${arch}" 1>&2
706: exit 1
707: fi
708: ;;
709: std*)
710: if test ${arch} = 32; then
711: echo " value = tme_htobe_u32(TME_SPARC_FORMAT3_RD);"
712: echo " tme_memory_bus_write32(((tme_shared tme_uint32_t *) memory) + 0, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t) * 2, sizeof(tme_uint${arch}_t));"
713: echo " value = tme_htobe_u32(TME_SPARC_FORMAT3_RD_ODD);"
714: echo " tme_memory_bus_write32(((tme_shared tme_uint32_t *) memory) + 1, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint32_t), sizeof(tme_uint${arch}_t));"
715: else
716: echo "$PROG fatal: need ${insn} support for sparc${arch}" 1>&2
717: exit 1
718: fi
719: ;;
720: ldstub*)
721: echo " value = tme_memory_atomic_xchg8(memory, 0xff, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint8_t));"
722: ;;
723: swap*)
724: echo " value = tme_htobe_u32(TME_SPARC_FORMAT3_RD);"
725: echo " value = tme_memory_atomic_xchg32((tme_shared tme_uint${size}_t *) memory, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint8_t));"
726: ;;
727: ld*)
728: echo " value = tme_memory_bus_read${size}((const tme_shared tme_uint${size}_t *) memory, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint${size}_t), sizeof(tme_uint${arch}_t));"
729: if test ${size} != 8; then
730: echo " value = tme_betoh_u${size}(value);"
731: fi
732: ;;
733: st*)
734: if test ${size} = 8; then swap_st= ; else swap_st="tme_htobe_u${size}"; fi
735: echo " value = ${swap_st}(TME_SPARC_FORMAT3_RD);"
736: echo " tme_memory_bus_write${size}((tme_shared tme_uint${size}_t *) memory, value, dtlb->tme_sparc_tlb_bus_rwlock, sizeof(tme_uint${size}_t), sizeof(tme_uint${arch}_t));"
737: ;;
738: *) echo "$PROG internal error: unknown memory insn ${insn}" 1>&2 ; exit 1 ;;
739: esac
740:
741: echo ""
742: echo " /* unbusy the DTLB entry: */"
743: echo " tme_sparc_tlb_unbusy(dtlb);"
744:
745: case "${insn}" in
746: ldd*) ;;
747: ld* | swap*)
748: if test `expr ${size} \< ${arch}` = 1; then
749: echo ""
750: echo " /* possibly sign-extend the loaded value: */"
751: echo " if (TME_SPARC_INSN & TME_BIT(22)) {"
752: echo " value = (tme_uint${arch}_t) (tme_int${arch}_t) (tme_int${size}_t) value;"
753: echo " }"
754: fi
755: echo ""
756: echo " /* set the loaded value: */"
757: echo " TME_SPARC_FORMAT3_RD = value;"
758: ;;
759: esac
760:
761: # if this is some kind of a load, log the value loaded:
762: #
763: case ${insn} in
764: ldd*)
765: echo ""
766: echo " /* log the value loaded: */"
767: # XXX FIXME - we can't verify a ldd yet:
768: #
769: echo " tme_sparc_log(ic, 1000, TME_OK,"
770: echo " (TME_SPARC_LOG_HANDLE(ic),"
771: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%08x 0x%08x\"),"
772: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data}),"
773: echo " address,"
774: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD,"
775: echo " (tme_uint32_t) TME_SPARC_FORMAT3_RD_ODD));"
776: ;;
777: ld* | ldstub* | swap*)
778: echo ""
779: echo " /* log the value loaded: */"
780: echo " tme_sparc_verify_mem${size}(ic, ${asi_mask_data}, address, (tme_uint${size}_t) TME_SPARC_FORMAT3_RD, TME_BUS_CYCLE_READ);"
781: echo " tme_sparc_log(ic, 1000, TME_OK,"
782: echo " (TME_SPARC_LOG_HANDLE(ic),"
783: echo " _(\"${insn}\t0x%02x:0x%0"`expr ${arch} / 4`"x:\t0x%0"`expr ${arch} / 4`"x\"),"
784: echo " TME_SPARC_ASI_MASK_WHICH(${asi_mask_data}),"
785: echo " address,"
786: echo " TME_SPARC_FORMAT3_RD));"
787: ;;
788: esac
789:
790: echo ""
791: echo " TME_SPARC_INSN_OK;"
792: echo "}"
793: fi
794:
795: # the jmpl instruction:
796: #
797: if test ${insn} = jmpl; then
798:
799: echo ""
800: echo "/* this does a sparc${arch} ${insn}: */"
801: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
802: echo "{"
803: echo " tme_uint${arch}_t pc_next_next;"
804: echo ""
805: echo " /* \"The JMPL instruction causes a register-indirect delayed control"
806: echo " transfer to the address given by r[rs1] + r[rs2] if the i field is"
807: echo " zero, or r[rs1] + sign_ext(simm13) if the i field is one. The JMPL"
808: echo " instruction copies the PC, which contains the address of the JMPL"
809: echo " instruction, into register r[rd]. If either of the low-order two"
810: echo " bits of the jump address is nonzero, a mem_address_not_aligned"
811: echo " trap occurs.\" */"
812: echo ""
813: echo " pc_next_next = TME_SPARC_FORMAT3_RS1 + TME_SPARC_FORMAT3_RS2;"
814: echo " if (__tme_predict_false((pc_next_next % sizeof(tme_uint32_t)) != 0)) {"
815: echo " TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_mem_address_not_aligned);"
816: echo " }"
817: echo ""
818: echo " /* write the PC of the jmpl into r[rd]: */"
819: echo " TME_SPARC_FORMAT3_RD = ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_PC);"
820: echo ""
821: echo " /* log an indirect call instruction, which has 15 (%o7) for rd: */"
822: echo " if (TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD) == 15) {"
823: echo " tme_sparc_log(ic, 250, TME_OK,"
824: echo " (TME_SPARC_LOG_HANDLE(ic),"
825: echo " _(\"call 0x%08x\"),"
826: echo " pc_next_next));"
827: echo " }"
828: echo ""
829: echo " /* log a ret or retl instruction, which has 0 (%g0) for rd,"
830: echo " either 31 (%i7) or 15 (%o7) for rs1, and 8 for simm13: */"
831: echo " else if ((TME_SPARC_INSN | (16 << 14))"
832: echo " == ((tme_uint32_t) (0x2 << 30) | (0 << 25) | (0x38 << 19) | (31 << 14) | (0x1 << 13) | 8)) {"
833: echo " tme_sparc_log(ic, 250, TME_OK,"
834: echo " (TME_SPARC_LOG_HANDLE(ic),"
835: echo " _(\"retl 0x%08x\"),"
836: echo " pc_next_next));"
837: echo " }"
838: echo ""
839: echo " /* set the delayed control transfer: */"
840: echo " ic->tme_sparc_ireg_uint${arch}(TME_SPARC_IREG_PC_NEXT_NEXT) = pc_next_next;"
841: echo ""
842: echo " TME_SPARC_INSN_OK;"
843: echo "}"
844: fi
845:
846: # the ldf instruction:
847: #
848: if test ${insn} = ldf; then
849:
850: echo ""
851: echo "/* this does a sparc${arch} ${insn}: */"
852: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
853: echo "{"
854: echo " unsigned int fpreg_number;"
855: echo ""
856: echo " TME_SPARC_INSN_FPU;"
857: echo ""
858: echo " /* decode rd: */"
859: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
860: echo ""
861: echo " /* make sure this floating-point register is single-precision: */"
862: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);"
863: echo ""
864: echo " /* do the load: */"
865: echo " tme_sparc${arch}_ld(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
866: echo ""
867: echo " /* set the floating-point register value: */"
868: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;"
869: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_single"
870: echo " = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift});"
871: echo ""
872: echo " TME_SPARC_INSN_OK;"
873: echo "}"
874: fi
875:
876: # the stf instruction:
877: #
878: if test ${insn} = stf; then
879:
880: echo ""
881: echo "/* this does a sparc${arch} ${insn}: */"
882: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
883: echo "{"
884: echo " unsigned int fpreg_number;"
885: echo " const tme_uint32_t *value_single;"
886: echo " tme_uint32_t value_single_buffer;"
887: echo ""
888: echo " TME_SPARC_INSN_FPU_STORE(sizeof(tme_uint32_t));"
889: echo ""
890: echo " /* decode rd: */"
891: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
892: echo ""
893: echo " /* make sure this floating-point register is single-precision: */"
894: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_SINGLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);"
895: echo ""
896: echo " /* get this single floating-point register in IEEE754 single-precision format: */"
897: echo " value_single = tme_ieee754_single_value_get(&ic->tme_sparc_fpu_fpregs[fpreg_number], &value_single_buffer);"
898: echo ""
899: echo " /* set the floating-point register value: */"
900: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}) = *value_single;"
901: echo ""
902: echo " /* do the store: */"
903: echo " tme_sparc${arch}_st(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
904: echo ""
905: echo " TME_SPARC_INSN_OK;"
906: echo "}"
907: fi
908:
909: # the lddf instruction:
910: #
911: if test ${insn} = lddf; then
912:
913: echo ""
914: echo "/* this does a sparc${arch} ${insn}: */"
915: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
916: echo "{"
917: echo " unsigned int fpreg_number;"
918: echo ""
919: echo " TME_SPARC_INSN_FPU;"
920: echo ""
921: echo " /* decode rd: */"
922: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
923: echo ""
924: echo " /* make sure rd is aligned: */"
925: echo " if (!tme_sparc_fpu_fpreg_aligned(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE)) {"
926: echo " fpreg_number -= 1;"
927: echo " }"
928: echo ""
929: echo " /* make sure that the double floating-point register is double-precision: */"
930: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);"
931: echo ""
932: echo " /* do the load: */"
933: echo " tme_sparc${arch}_ldd(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
934: echo ""
935: echo " /* set the double floating-point register value: */"
936: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;"
937: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint32_hi"
938: echo " = ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 0);"
939: echo " ic->tme_sparc_fpu_fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint32_lo"
940: echo " = ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1);"
941: echo ""
942: echo " TME_SPARC_INSN_OK;"
943: echo "}"
944: fi
945:
946: # the stdf instruction:
947: #
948: if test ${insn} = stdf; then
949:
950: echo ""
951: echo "/* this does a sparc${arch} ${insn}: */"
952: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
953: echo "{"
954: echo " unsigned int fpreg_number;"
955: echo " const union tme_value64 *value_double;"
956: echo " union tme_value64 value_double_buffer;"
957: echo ""
958: echo " TME_SPARC_INSN_FPU_STORE(sizeof(tme_uint32_t) * 2);"
959: echo ""
960: echo " /* decode rd: */"
961: echo " fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, TME_SPARC_FORMAT3_MASK_RD);"
962: echo ""
963: echo " /* make sure rd is aligned: */"
964: echo " if (!tme_sparc_fpu_fpreg_aligned(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE)) {"
965: echo " fpreg_number -= 1;"
966: echo " }"
967: echo ""
968: echo " /* make sure the double floating-point register is double-precision: */"
969: echo " tme_sparc_fpu_fpreg_format(ic, fpreg_number, TME_IEEE754_FPREG_FORMAT_DOUBLE | TME_IEEE754_FPREG_FORMAT_BUILTIN);"
970: echo ""
971: echo " /* get this double floating-point register in IEEE754 double-precision format: */"
972: echo " value_double = tme_ieee754_double_value_get(&ic->tme_sparc_fpu_fpregs[fpreg_number], &value_double_buffer);"
973: echo ""
974: echo " /* set the floating-point register value: */"
975: echo " ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 0)"
976: echo " = value_double->tme_value64_uint32_hi;"
977: echo " ic->tme_sparc_ireg_uint32((TME_SPARC_IREG_FPX${reg32_shift}) + 1)"
978: echo " = value_double->tme_value64_uint32_lo;"
979: echo ""
980: echo " /* do the store: */"
981: echo " tme_sparc${arch}_std(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
982: echo ""
983: echo " TME_SPARC_INSN_OK;"
984: echo "}"
985: fi
986:
987: # the ldfsr instruction:
988: #
989: if test ${insn} = ldfsr; then
990:
991: echo ""
992: echo "/* this does a sparc${arch} ${insn}: */"
993: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
994: echo "{"
995: echo " tme_uint32_t fsr;"
996: echo ""
997: echo " TME_SPARC_INSN_FPU;"
998: echo ""
999: echo " /* do the load: */"
1000: echo " tme_sparc${arch}_ld(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
1001: echo ""
1002: echo " /* update the FSR: */"
1003: echo " fsr = ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift});"
1004: echo " /* \"An LDFSR instruction does not affect ftt.\" */"
1005: echo " /* \"The LDFSR instruction does not affect qne.\" */"
1006: echo " fsr &= ~(TME_SPARC_FSR_VER | TME_SPARC_FSR_FTT | TME_SPARC_FSR_QNE);"
1007: echo " ic->tme_sparc_fpu_fsr = (ic->tme_sparc_fpu_fsr & (TME_SPARC_FSR_VER | TME_SPARC_FSR_FTT | TME_SPARC_FSR_QNE)) | fsr;"
1008: echo ""
1009: echo " TME_SPARC_INSN_OK;"
1010: echo "}"
1011: fi
1012:
1013: # the stfsr instruction:
1014: #
1015: if test ${insn} = stfsr; then
1016:
1017: echo ""
1018: echo "/* this does a sparc${arch} ${insn}: */"
1019: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
1020: echo "{"
1021: echo ""
1022: echo " TME_SPARC_INSN_FPU_STORE(sizeof(ic->tme_sparc_fpu_fsr));"
1023: echo ""
1024: echo " /* set the FSR value to store: */"
1025: echo " ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}) = ic->tme_sparc_fpu_fsr;"
1026: echo ""
1027: echo " /* do the store: */"
1028: echo " tme_sparc${arch}_st(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX${reg32_shift}));"
1029: echo ""
1030: echo " TME_SPARC_INSN_OK;"
1031: echo "}"
1032: fi
1033:
1034: # the fpop1 and fpop2 instructions:
1035: #
1036: if test ${insn} = fpop1 || test ${insn} = fpop2; then
1037:
1038: echo ""
1039: echo "/* this does a sparc${arch} ${insn}: */"
1040: echo "TME_SPARC_FORMAT3(tme_sparc${arch}_${insn}, tme_uint${arch}_t)"
1041: echo "{"
1042: echo " TME_SPARC_INSN_FPU;"
1043: echo " tme_sparc_fpu_${insn}(ic);"
1044: echo " TME_SPARC_INSN_OK;"
1045: echo "}"
1046: fi
1047:
1048: done
1049:
1050: # the slow load and store functions:
1051: #
1052: for slow in load store; do
1053:
1054: if test ${slow} = load; then
1055: cycle="read"
1056: capcycle="READ"
1057: if $header; then
1058: echo "const tme_shared tme_uint8_t *tme_sparc${arch}_${slow} _TME_P((struct tme_sparc *, tme_uint${arch}_t, unsigned int));"
1059: continue
1060: fi
1061: else
1062: cycle="write"
1063: capcycle="WRITE"
1064: if $header; then
1065: echo "tme_shared tme_uint8_t *tme_sparc${arch}_${slow} _TME_P((struct tme_sparc *, tme_uint${arch}_t, const tme_uint${arch}_t *, unsigned int));"
1066: continue
1067: fi
1068: fi
1069:
1070: echo ""
1071: echo "/* this does a slow ${slow}: */"
1072: if test ${slow} = load; then echo -n "const "; fi
1073: echo "tme_shared tme_uint8_t *"
1074: echo "tme_sparc${arch}_${slow}(struct tme_sparc *ic, "
1075: echo " tme_uint${arch}_t address, "
1076: if test ${slow} = store; then
1077: echo " const tme_uint${arch}_t * const _rd,"
1078: fi
1079: echo " const unsigned int flags)"
1080: echo "{"
1081:
1082: # our locals:
1083: #
1084: echo " unsigned int size;"
1085: echo " tme_uint32_t asi_mask_data;"
1086: echo " struct tme_sparc_tlb *dtlb;"
1087: echo " tme_bus_addr_t physical_address;"
1088: echo " int shift;"
1089: echo " struct tme_bus_cycle cycle;"
1090: echo " unsigned int transferred, resid, cycle_size;"
1091: echo " unsigned int trap;"
1092: echo " int err;"
1093: if test ${slow} = store; then
1094: echo " tme_uint${arch}_t stored_registers[2];"
1095: echo " const tme_uint8_t *buffer;"
1096: buffer=buffer
1097: else
1098: buffer="&ic->tme_sparc_memory_buffer[0]"
1099: fi
1100:
1101: echo ""
1102: echo " /* get the transfer size. we can do at most a 64-bit transfer: */"
1103: echo " size = (flags % (sizeof(tme_uint64_t) * 2));"
1104:
1105: echo ""
1106: echo " /* get the DTLB entry. our caller has already busied it: */"
1107: echo " dtlb = TME_SPARC_DTLB_ENTRY(ic, address);"
1108:
1109: echo ""
1110: echo " /* if the address is not aligned: */"
1111: echo " if (__tme_predict_false((address & (size - 1)) != 0)) {"
1112: echo " tme_sparc_tlb_unbusy(dtlb);"
1113: echo " tme_sparc${arch}_trap(ic, TME_SPARC_TRAP_mem_address_not_aligned);"
1114: echo " }"
1115:
1116: echo ""
1117: echo " /* if this is a ldd or a std (and not an lddf or an stdf)"
1118: echo " and the destination register address is odd: */"
1119: echo " /* NB: we detect lddf and stdf by testing bit 24 in the"
1120: echo " instruction word: */"
1121: echo " if (__tme_predict_false(size == (sizeof(tme_uint32_t) * 2)"
1122: echo " && (TME_SPARC_INSN & TME_BIT(25)) != 0"
1123: echo " && (TME_SPARC_INSN & TME_BIT(24)) == 0)) {"
1124: echo " tme_sparc_tlb_unbusy(dtlb);"
1125: echo " tme_sparc${arch}_trap(ic, TME_SPARC_TRAP_illegal_instruction);"
1126: echo " }"
1127:
1128: echo ""
1129: echo " /* get the ASI and its mask: */"
1130: echo " asi_mask_data = ic->tme_sparc_asi_mask_data;"
1131: echo " if (__tme_predict_false((flags & TME_SPARC_SLOW_FLAG_INSN) != 0)) {"
1132: echo " asi_mask_data = ic->tme_sparc_asi_mask_insn;"
1133: echo " }"
1134: echo " if (__tme_predict_false((flags & TME_SPARC_SLOW_FLAG_A) != 0)) {"
1135: echo " asi_mask_data = _tme_sparc${arch}_alternate_asi_mask(ic);"
1136: echo " }"
1137:
1138: if test ${slow} = store; then
1139: echo ""
1140: echo " /* store big-endian versions of the registers to store in"
1141: echo " a buffer. we always assume that this is a std and copy"
1142: echo " r[rd] and r[rd + 1] into the buffer: */"
1143: echo " stored_registers[0] = tme_htobe_u${arch}(TME_SPARC_FORMAT3_RD);"
1144: echo " stored_registers[1] = tme_htobe_u${arch}(TME_SPARC_FORMAT3_RD_ODD);"
1145: echo ""
1146: echo " /* make the initial pointer into the buffer: */"
1147: echo " buffer = (const tme_uint8_t *) stored_registers;"
1148: echo " if (size < sizeof(tme_uint32_t)) {"
1149: echo " buffer += sizeof(tme_uint32_t) - size;"
1150: echo " }"
1151: fi
1152: echo ""
1153: echo " /* loop until the ${slow} is completed: */"
1154: echo " trap = TME_SPARC_TRAP_none;"
1155: echo " transferred = 0;"
1156: echo " do {"
1157: echo ""
1158: echo " /* while the DTLB entry is invalid, or does not cover this address"
1159: echo " and address space, or if it does not allow for slow or fast ${cycle}s: */"
1160: echo " for (; (tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb)"
1161: echo " || (dtlb->tme_sparc_tlb_addr_first > address)"
1162: echo " || (dtlb->tme_sparc_tlb_addr_last < address)"
1163: echo " || (!TME_SPARC_TLB_ASI_MASK_OK(dtlb, asi_mask_data))"
1164: echo " || (dtlb->tme_sparc_tlb_emulator_off_${cycle} == TME_EMULATOR_OFF_UNDEF"
1165: echo " && (dtlb->tme_sparc_tlb_cycles_ok & TME_BUS_CYCLE_${capcycle}) == 0)); ) {"
1166: echo ""
1167: echo " /* unbusy this DTLB entry for filling: */"
1168: echo " tme_bus_tlb_unbusy_fill(&dtlb->tme_sparc_tlb_bus_tlb);"
1169: echo ""
1170: echo " /* we never fill TLB entries on the stack because we never"
1171: echo " callout multiple fills at the same time, so the global TLB"
1172: echo " entry pointer always points back to the TLB entry. this"
1173: echo " also means that we do not have to call tme_bus_tlb_back()"
1174: echo " after the fill: */"
1175: echo " dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_global = &dtlb->tme_sparc_tlb_bus_tlb;"
1176: echo ""
1177: echo " /* reload the DTLB entry: */"
1178: echo " tme_sparc_callout_unlock(ic);"
1179: echo "#ifdef _TME_SPARC_STATS"
1180: echo " ic->tme_sparc_stats.tme_sparc_stats_dtlb_fill++;"
1181: echo "#endif /* _TME_SPARC_STATS */"
1182: echo " err = (*ic->_tme_sparc_bus_connection->tme_sparc_bus_tlb_fill)"
1183: echo " (ic->_tme_sparc_bus_connection,"
1184: echo " dtlb,"
1185: echo " asi_mask_data,"
1186: echo " address,"
1187: echo " TME_BUS_CYCLE_${capcycle});"
1188: echo " assert (err == TME_OK);"
1189: echo " tme_sparc_callout_relock(ic);"
1190: echo ""
1191: echo " /* rebusy the DTLB entry: */"
1192: echo " tme_sparc_tlb_busy(dtlb);"
1193: echo " }"
1194:
1195: echo ""
1196: echo " /* if this DTLB entry allows fast ${cycle}s: */"
1197: echo " if (__tme_predict_true(dtlb->tme_sparc_tlb_emulator_off_${cycle} != TME_EMULATOR_OFF_UNDEF)) {"
1198: echo ""
1199: echo " /* if we have not transferred anything yet, and this"
1200: echo " DTLB entry covers all of the addresses and allows"
1201: echo " fast transfers: */"
1202: echo " if (__tme_predict_true(transferred == 0"
1203: echo " && dtlb->tme_sparc_tlb_addr_last >= address + (size - 1)"
1204: if test ${slow} = store; then
1205: echo ""
1206: echo " && ((flags & TME_SPARC_SLOW_FLAG_ATOMIC) == 0"
1207: echo -n " || dtlb->tme_sparc_tlb_emulator_off_read == dtlb->tme_sparc_tlb_emulator_off_${cycle})"
1208: fi
1209: echo ")) {"
1210:
1211: echo ""
1212: echo " /* return and let our caller do the transfer: */"
1213: echo " return (dtlb->tme_sparc_tlb_emulator_off_${cycle});"
1214: echo " }"
1215: echo ""
1216: echo " /* calculate the cycle size: */"
1217: echo " cycle_size = (dtlb->tme_sparc_tlb_addr_last - address) + 1;"
1218: echo " cycle_size = TME_MIN(cycle_size, sizeof(tme_uint${arch}_t) - (address % sizeof(tme_uint${arch}_t)));"
1219: echo " cycle_size = TME_MIN(cycle_size, size - transferred);"
1220: echo " cycle.tme_bus_cycle_size = cycle_size;"
1221: echo ""
1222: echo " /* do a ${cycle}: */"
1223: echo " tme_memory_bus_${cycle}_buffer((dtlb->tme_sparc_tlb_emulator_off_${cycle} + address),"
1224: echo " (${buffer} + transferred),"
1225: echo " cycle_size,"
1226: echo " dtlb->tme_sparc_tlb_bus_rwlock,"
1227: echo " sizeof(tme_uint8_t),"
1228: echo " sizeof(tme_uint32_t));"
1229: echo " }"
1230: echo ""
1231: echo " /* otherwise, this DTLB entry does not allow fast ${cycle}s: */"
1232: echo " else {"
1233: echo ""
1234: echo " /* make the bus cycle structure: */"
1235: echo " resid = size - transferred;"
1236: echo " cycle.tme_bus_cycle_type = TME_BUS_CYCLE_${capcycle};"
1237: echo " cycle.tme_bus_cycle_buffer = (tme_uint8_t *) (${buffer} + transferred);"
1238: echo " cycle.tme_bus_cycle_buffer_increment = 1;"
1239: echo " cycle_size = TME_MIN(resid, sizeof(tme_uint${arch}_t) - (address % sizeof(tme_uint${arch}_t)));"
1240: echo " cycle.tme_bus_cycle_size = cycle_size;"
1241: echo " cycle.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS${arch}_LOG2);"
1242: echo " cycle.tme_bus_cycle_lane_routing = "
1243: echo " &tme_sparc${arch}_router[TME_SPARC_BUS_ROUTER_INDEX(TME_BUS${arch}_LOG2, cycle_size, address)];"
1244: echo ""
1245: echo " /* form the physical address for the bus cycle handler: */"
1246: echo " physical_address = dtlb->tme_sparc_tlb_addr_offset + address;"
1247: echo " shift = dtlb->tme_sparc_tlb_addr_shift;"
1248: echo " if (shift < 0) {"
1249: echo " physical_address <<= (0 - shift);"
1250: echo " }"
1251: echo " else if (shift > 0) {"
1252: echo " physical_address >>= shift;"
1253: echo " }"
1254: echo " cycle.tme_bus_cycle_address = physical_address;"
1255:
1256: echo ""
1257: echo " /* callout the bus cycle: */"
1258: echo " tme_sparc_tlb_unbusy(dtlb);"
1259: echo " tme_sparc_callout_unlock(ic);"
1260: echo " err = (*dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycle)"
1261: echo " (dtlb->tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycle_private, &cycle);"
1262: echo " tme_sparc_callout_relock(ic);"
1263: echo " tme_sparc_tlb_busy(dtlb);"
1264: echo ""
1265: echo " /* if the TLB entry was invalidated before the ${slow}: */"
1266: echo " if (err == EBADF"
1267: echo " && tme_bus_tlb_is_invalid(&dtlb->tme_sparc_tlb_bus_tlb)) {"
1268: echo " cycle.tme_bus_cycle_size = 0;"
1269: echo " }"
1270: echo ""
1271: echo " /* otherwise, any other error might be a bus error: */"
1272: echo " else if (err != TME_OK) {"
1273: echo ""
1274: echo " /* if a real bus error may have happened, instead of"
1275: echo " some synchronous event: */"
1276: echo " if (err != TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {"
1277: echo ""
1278: echo " /* call the bus fault handlers: */"
1279: echo " err = tme_bus_tlb_fault(&dtlb->tme_sparc_tlb_bus_tlb, &cycle, err);"
1280: echo " }"
1281: echo ""
1282: echo " /* if some synchronous event has happened: */"
1283: echo " if (err == TME_BUS_CYCLE_SYNCHRONOUS_EVENT) {"
1284: echo ""
1285: echo " /* after the currently executing instruction finishes, check"
1286: echo " for external resets, halts, or interrupts: */"
1287: echo " ic->_tme_sparc_instruction_burst_remaining = 0;"
1288: echo " }"
1289: echo ""
1290: echo " /* otherwise, if a real bus fault happened: */"
1291: echo " else if (err != TME_OK) {"
1292: echo " trap = (*ic->_tme_sparc_bus_fault)(ic, &cycle, flags, err);"
1293: echo " if (trap != TME_SPARC_TRAP_none) {"
1294: echo " break;"
1295: echo " }"
1296: echo " }"
1297: echo " }"
1298:
1299: if test ${slow} = store; then
1300: echo ""
1301: echo " /* if this was an atomic operation, and data was transferred: */"
1302: echo " if (__tme_predict_false((flags & TME_SPARC_SLOW_FLAG_ATOMIC) != 0"
1303: echo " && cycle.tme_bus_cycle_size > 0)) {"
1304: echo ""
1305: echo " /* we do not support atomic operations in TLB entries that"
1306: echo " do not support both fast reads and fast writes. assuming"
1307: echo " that all atomic operations are to regular memory, we"
1308: echo " should always get fast read and fast write TLBs. when"
1309: echo " we do not, it should only be because the memory has been"
1310: echo " made read-only in the MMU. the write above was supposed"
1311: echo " to cause a fault (with the instruction rerun later with"
1312: echo " a fast read and fast write TLB entry), but instead it"
1313: echo " succeeded and transferred some data. we have modified"
1314: echo " memory and cannot recover: */"
1315: echo " abort();"
1316: echo " }"
1317: fi
1318: echo " }"
1319:
1320: echo ""
1321: echo " /* update: */"
1322: echo " address += cycle.tme_bus_cycle_size;"
1323: echo " transferred += cycle.tme_bus_cycle_size;"
1324: echo " } while (transferred < size);"
1325:
1326: echo ""
1327: echo " /* if we faulted, start trap processing: */"
1328: echo " if (__tme_predict_false(trap != TME_SPARC_TRAP_none)) {"
1329: echo " tme_sparc_tlb_unbusy(dtlb);"
1330: echo " tme_sparc${arch}_trap(ic, trap);"
1331: echo " }"
1332:
1333: echo ""
1334: if test ${slow} = load; then
1335: echo " return (ic->tme_sparc_memory_buffer - (address - size));"
1336: else
1337: echo " return ((tme_uint8_t *) TME_EMULATOR_OFF_UNDEF);"
1338: fi
1339: echo "}"
1340: done
1341:
1342: # unfix the architecture version:
1343: #
1344: if $header; then :; else
1345: echo ""
1346: echo "#undef TME_SPARC_VERSION"
1347: echo "#define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic)"
1348: fi
1349:
1350: # the sparc64 support depends on a 64-bit integer type:
1351: #
1352: if test ${arch} = 64; then
1353: echo ""
1354: echo "#endif /* TME_HAVE_INT64_T */"
1355: fi
1356: done
1357:
1358: # done:
1359: #
1360: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.