|
| 1 | + 10 REM ============================================================ |
| 2 | + 20 REM 32x32 -> 64 multiply test harness for BBC BASIC |
| 3 | + 30 REM |
| 4 | + 40 REM Replace PROCasmmul at lines 9000-9070 with your MULX call. |
| 5 | + 50 REM |
| 6 | + 60 REM Operands are unsigned 32-bit, passed as: |
| 7 | + 70 REM AH%:AL% and BH%:BL% |
| 8 | + 80 REM where each half is a 16-bit unsigned word 0..65535. |
| 9 | + 90 REM |
| 10 | + 100 REM Returned / compared result is 64-bit as four 16-bit words: |
| 11 | + 110 REM R3%:R2%:R1%:R0% |
| 12 | + 120 REM ============================================================ |
| 13 | + |
| 14 | + 130 MODE 7 |
| 15 | + 140 ON ERROR PRINT REPORT$;" at line ";ERL : END |
| 16 | + |
| 17 | + 150 DIM EDGE%(63) |
| 18 | + 160 DIM OPH%(1023), OPL%(1023) |
| 19 | + 170 DIM AB%(3), BB%(3), S%(7) |
| 20 | + |
| 21 | + 180 PROCinitedges |
| 22 | + 190 PROCbuildops |
| 23 | + |
| 24 | + 200 PRINT "Operand cases built: ";OPN% |
| 25 | + 210 PRINT "Running pairwise boundary tests..." |
| 26 | + 220 PRINT |
| 27 | + |
| 28 | + 230 FAIL%=0 |
| 29 | + 240 TESTS%=0 |
| 30 | + |
| 31 | + 250 FOR I%=0 TO OPN%-1 |
| 32 | + 260 FOR J%=0 TO OPN%-1 |
| 33 | + 270 PROCtestpair(OPH%(I%), OPL%(I%), OPH%(J%), OPL%(J%)) |
| 34 | + 280 NEXT |
| 35 | + 290 NEXT |
| 36 | + |
| 37 | + 300 PRINT |
| 38 | + 310 PRINT "Running random tests..." |
| 39 | + 320 FOR I%=1 TO 5000 |
| 40 | + 330 AH%=RND(65536)-1 |
| 41 | + 340 AL%=RND(65536)-1 |
| 42 | + 350 BH%=RND(65536)-1 |
| 43 | + 360 BL%=RND(65536)-1 |
| 44 | + 370 PROCtestpair(AH%, AL%, BH%, BL%) |
| 45 | + 380 NEXT |
| 46 | + |
| 47 | + 390 PRINT |
| 48 | + 400 PRINT "Tests run : ";TESTS% |
| 49 | + 410 PRINT "Failures : ";FAIL% |
| 50 | + 420 IF FAIL%=0 PRINT "All tests passed." |
| 51 | + 430 END |
| 52 | + |
| 53 | + 1000 DEF PROCinitedges |
| 54 | + 1010 LOCAL I%,V% |
| 55 | + 1020 RESTORE 8000 |
| 56 | + 1030 I%=0 |
| 57 | + 1040 REPEAT |
| 58 | + 1050 READ V% |
| 59 | + 1060 IF V%<>-1 EDGE%(I%)=V% : I%=I%+1 |
| 60 | + 1070 UNTIL V%=-1 |
| 61 | + 1080 EDGECOUNT%=I% |
| 62 | + 1090 ENDPROC |
| 63 | + |
| 64 | + 1100 DEF PROCbuildops |
| 65 | + 1110 LOCAL I%,V% |
| 66 | + 1120 OPN%=0 |
| 67 | + 1130 REM Core edge-driven patterns |
| 68 | + 1140 FOR I%=0 TO EDGECOUNT%-1 |
| 69 | + 1150 V%=EDGE%(I%) |
| 70 | + 1160 PROCaddop(0, V%) |
| 71 | + 1170 PROCaddop(V%, 0) |
| 72 | + 1180 PROCaddop(V%, V%) |
| 73 | + 1190 PROCaddop(65535, V%) |
| 74 | + 1200 PROCaddop(V%, 65535) |
| 75 | + 1210 PROCaddop(65535-V%, V%) |
| 76 | + 1220 PROCaddop(V%, 65535-V%) |
| 77 | + 1230 NEXT |
| 78 | + 1240 REM Fixed byte/word patterns |
| 79 | + 1250 PROCaddop(&0000, &0000) |
| 80 | + 1260 PROCaddop(&0000, &0001) |
| 81 | + 1270 PROCaddop(&0000, &00FF) |
| 82 | + 1280 PROCaddop(&0000, &0100) |
| 83 | + 1290 PROCaddop(&0000, &7FFF) |
| 84 | + 1300 PROCaddop(&0000, &8000) |
| 85 | + 1310 PROCaddop(&0000, &FFFF) |
| 86 | + 1320 PROCaddop(&0001, &0000) |
| 87 | + 1330 PROCaddop(&0001, &0001) |
| 88 | + 1340 PROCaddop(&0001, &FFFF) |
| 89 | + 1350 PROCaddop(&00FF, &00FF) |
| 90 | + 1360 PROCaddop(&00FF, &FF00) |
| 91 | + 1370 PROCaddop(&0100, &0100) |
| 92 | + 1380 PROCaddop(&7FFF, &7FFF) |
| 93 | + 1390 PROCaddop(&8000, &8000) |
| 94 | + 1400 PROCaddop(&FFFF, &0001) |
| 95 | + 1410 PROCaddop(&FFFF, &FFFF) |
| 96 | + 1420 PROCaddop(&00FF, &FFFF) |
| 97 | + 1430 PROCaddop(&FFFF, &00FF) |
| 98 | + 1440 PROCaddop(&FF00, &00FF) |
| 99 | + 1450 PROCaddop(&00FF, &FF00) |
| 100 | + 1460 PROCaddop(&1234, &5678) |
| 101 | + 1470 PROCaddop(&89AB, &CDEF) |
| 102 | + 1480 PROCaddop(&1357, &9BDF) |
| 103 | + 1490 PROCaddop(&AAAA, &5555) |
| 104 | + 1500 PROCaddop(&5555, &AAAA) |
| 105 | + 1510 PROCdedup |
| 106 | + 1520 ENDPROC |
| 107 | + |
| 108 | + 1600 DEF PROCaddop(HI%, LO%) |
| 109 | + 1610 IF HI%<0 HI%=HI%+65536 |
| 110 | + 1620 IF LO%<0 LO%=LO%+65536 |
| 111 | + 1630 OPH%(OPN%)=HI% |
| 112 | + 1640 OPL%(OPN%)=LO% |
| 113 | + 1650 OPN%=OPN%+1 |
| 114 | + 1660 ENDPROC |
| 115 | + |
| 116 | + 1700 DEF PROCdedup |
| 117 | + 1710 LOCAL I%,J%,K% |
| 118 | + 1720 FOR I%=0 TO OPN%-1 |
| 119 | + 1730 J%=I%+1 |
| 120 | + 1740 REPEAT |
| 121 | + 1750 IF J%>=OPN% THEN EXIT REPEAT |
| 122 | + 1760 IF OPH%(I%)=OPH%(J%) AND OPL%(I%)=OPL%(J%) THEN |
| 123 | + 1770 FOR K%=J% TO OPN%-2 |
| 124 | + 1780 OPH%(K%)=OPH%(K%+1) |
| 125 | + 1790 OPL%(K%)=OPL%(K%+1) |
| 126 | + 1800 NEXT |
| 127 | + 1810 OPN%=OPN%-1 |
| 128 | + 1820 ELSE |
| 129 | + 1830 J%=J%+1 |
| 130 | + 1840 ENDIF |
| 131 | + 1850 UNTIL FALSE |
| 132 | + 1860 NEXT |
| 133 | + 1870 ENDPROC |
| 134 | + |
| 135 | + 2000 DEF PROCtestpair(AH%, AL%, BH%, BL%) |
| 136 | + 2010 TESTS%=TESTS%+1 |
| 137 | + 2020 PROCrefmul(AH%, AL%, BH%, BL%) |
| 138 | + 2030 PROCasmmul(AH%, AL%, BH%, BL%) |
| 139 | + |
| 140 | + 2040 IF R0%<>T0% OR R1%<>T1% OR R2%<>T2% OR R3%<>T3% THEN |
| 141 | + 2050 FAIL%=FAIL%+1 |
| 142 | + 2060 PRINT "FAIL ";FAIL% |
| 143 | + 2070 PRINT " A=&";FNHEX8(AH%,AL%) |
| 144 | + 2080 PRINT " B=&";FNHEX8(BH%,BL%) |
| 145 | + 2090 PRINT " expected =&";FNHEX16(R3%,R2%,R1%,R0%) |
| 146 | + 2100 PRINT " got =&";FNHEX16(T3%,T2%,T1%,T0%) |
| 147 | + 2110 PRINT |
| 148 | + 2120 IF FAIL%>=50 THEN PRINT "Stopping after 50 failures." : END |
| 149 | + 2130 ENDIF |
| 150 | + 2140 ENDPROC |
| 151 | + |
| 152 | + 3000 DEF PROCrefmul(AH%, AL%, BH%, BL%) |
| 153 | + 3010 LOCAL I%,J%,K%,C% |
| 154 | + 3020 AB%(0)=AL% MOD 256 |
| 155 | + 3030 AB%(1)=AL% DIV 256 |
| 156 | + 3040 AB%(2)=AH% MOD 256 |
| 157 | + 3050 AB%(3)=AH% DIV 256 |
| 158 | + 3060 BB%(0)=BL% MOD 256 |
| 159 | + 3070 BB%(1)=BL% DIV 256 |
| 160 | + 3080 BB%(2)=BH% MOD 256 |
| 161 | + 3090 BB%(3)=BH% DIV 256 |
| 162 | + |
| 163 | + 3100 FOR I%=0 TO 7 |
| 164 | + 3110 S%(I%)=0 |
| 165 | + 3120 NEXT |
| 166 | + |
| 167 | + 3130 FOR I%=0 TO 3 |
| 168 | + 3140 FOR J%=0 TO 3 |
| 169 | + 3150 S%(I%+J%)=S%(I%+J%)+AB%(I%)*BB%(J%) |
| 170 | + 3160 NEXT |
| 171 | + 3170 NEXT |
| 172 | + |
| 173 | + 3180 FOR K%=0 TO 6 |
| 174 | + 3190 C%=S%(K%) DIV 256 |
| 175 | + 3200 S%(K%)=S%(K%) MOD 256 |
| 176 | + 3210 S%(K%+1)=S%(K%+1)+C% |
| 177 | + 3220 NEXT |
| 178 | + 3230 S%(7)=S%(7) MOD 256 |
| 179 | + |
| 180 | + 3240 R0%=S%(0)+256*S%(1) |
| 181 | + 3250 R1%=S%(2)+256*S%(3) |
| 182 | + 3260 R2%=S%(4)+256*S%(5) |
| 183 | + 3270 R3%=S%(6)+256*S%(7) |
| 184 | + 3280 ENDPROC |
| 185 | + |
| 186 | + 4000 DEF FNHEX4(W%) |
| 187 | + 4010 LOCAL D%,S$ |
| 188 | + 4020 W%=W% MOD 65536 |
| 189 | + 4030 S$="" |
| 190 | + 4040 FOR D%=3 TO 0 STEP -1 |
| 191 | + 4050 S$=S$+MID$("0123456789ABCDEF", (W% DIV (16^D%)) MOD 16 + 1, 1) |
| 192 | + 4060 NEXT |
| 193 | + 4070 =S$ |
| 194 | + |
| 195 | + 4100 DEF FNHEX8(HI%,LO%) |
| 196 | + 4110 =FNHEX4(HI%)+FNHEX4(LO%) |
| 197 | + |
| 198 | + 4200 DEF FNHEX16(W3%,W2%,W1%,W0%) |
| 199 | + 4210 =FNHEX4(W3%)+FNHEX4(W2%)+FNHEX4(W1%)+FNHEX4(W0%) |
| 200 | + |
| 201 | + 9000 DEF PROCasmmul(AH%, AL%, BH%, BL%) |
| 202 | + 9010 REM ============================================================ |
| 203 | + 9020 REM Replace this stub with your actual MULX call. |
| 204 | + 9030 REM It must set: |
| 205 | + 9040 REM T0% = low 16 bits |
| 206 | + 9050 REM T1% = next 16 bits |
| 207 | + 9060 REM T2% = next 16 bits |
| 208 | + 9070 REM T3% = high 16 bits |
| 209 | + 9080 REM |
| 210 | + 9090 REM Temporary default: use reference result so the harness runs. |
| 211 | + 9100 REM ============================================================ |
| 212 | + 9110 PROCrefmul(AH%, AL%, BH%, BL%) |
| 213 | + 9120 T0%=R0% |
| 214 | + 9130 T1%=R1% |
| 215 | + 9140 T2%=R2% |
| 216 | + 9150 T3%=R3% |
| 217 | + 9160 ENDPROC |
| 218 | + |
| 219 | + 8000 DATA 0 |
| 220 | + 8010 DATA 1,2,3,4,7,8,15,16,31,32,63,64,127,128 |
| 221 | + 8020 DATA 255,256,257,511,512,513 |
| 222 | + 8030 DATA 1023,1024,1025,2047,2048,2049 |
| 223 | + 8040 DATA 4095,4096,4097,8191,8192,8193 |
| 224 | + 8050 DATA 16383,16384,16385,32767,32768,32769 |
| 225 | + 8060 DATA 49151,49152,49153,65279,65280,65281 |
| 226 | + 8070 DATA 65533,65534,65535 |
| 227 | + 8080 DATA -1 |
0 commit comments