70
70
71
71
#define LOG_GENERAL (1U << 0 )
72
72
#define LOG_MMU (1U << 1 )
73
+ #define LOG_FPU (1U << 2 )
73
74
74
75
#define VERBOSE 1
75
76
#include " logmacro.h"
@@ -565,6 +566,9 @@ class tek440x_state : public driver_device
565
566
u8 mouse_r (offs_t offset);
566
567
void mouse_w (u8 data);
567
568
void led_w (u8 data);
569
+
570
+ void fpu_latch32_result (void *);
571
+ void fpu_latch64_result (void *);
568
572
u16 fpu_r (offs_t offset);
569
573
void fpu_w (offs_t offset, u16 data);
570
574
u16 videoaddr_r (offs_t offset);
@@ -645,6 +649,7 @@ class tek440x_state : public driver_device
645
649
u16 m_operand;
646
650
u16 m_lswoperand[5 ];
647
651
u16 m_mswoperand[5 ];
652
+ uint64_t m_result;
648
653
649
654
u16 m_videoaddr[4 ];
650
655
u8 m_videocntl;
@@ -1006,25 +1011,49 @@ void tek440x_state::mapcntl_w(u8 data)
1006
1011
1007
1012
}
1008
1013
1014
+ enum {FLOATRESULT=0 , DOUBLERESULT=1 , INTRESULT=2 };
1009
1015
1010
1016
enum {
1011
- FLOAT = 0xbe ,
1012
- DOUBLE = 0x3e ,
1017
+ FPCALC = 0xbe ,
1018
+ FPCONV = 0x3e ,
1019
+
1020
+ SETS = 0x0b42 ,
1021
+ GETS = 0x3342 ,
1022
+
1023
+ FItoF = 0x0742 ,
1024
+ FFtoIr = 0x2742 ,
1025
+ FFtoIt = 0x2f42 ,
1026
+ FFtoIf = 0x3f42 ,
1027
+ FFtoD = 0x1b42 ,
1028
+
1029
+ FItoD = 0x0342 ,
1030
+ FDtoIr = 0x2342 ,
1031
+ FDtoIt = 0x2b42 ,
1032
+ FDtoIf = 0x3b42 ,
1033
+ FDtoF = 0x1642 ,
1013
1034
1014
1035
FADD = 0x0142 ,
1015
1036
FSUB = 0x1142 ,
1016
1037
FMUL = 0x3142 ,
1017
1038
FDIV = 0x2142 ,
1018
1039
FCMP = 0x0942 ,
1019
-
1020
-
1021
- DMUL = 0x3342 ,
1022
-
1040
+ FNEG = 0xff00 , // unused
1041
+ FABS = 0xff01 , // unused
1042
+
1043
+ DADD = 0x0042 ,
1044
+ DSUB = 0x1042 ,
1045
+ DMUL = 0x3042 ,
1046
+ DDIV = 0x2042 ,
1047
+ DCMP = 0x0842 ,
1048
+ DNEG = 0xff80 , // unused
1049
+ DABS = 0xff81 , // unused
1023
1050
1024
1051
};
1025
1052
1026
1053
void tek440x_state::fpu_w (offs_t offset, u16 data)
1027
1054
{
1055
+ LOG (" fpu_w: %08x <= 0x%04x\n " , offset, data);
1056
+
1028
1057
switch (offset)
1029
1058
{
1030
1059
default :
@@ -1039,68 +1068,279 @@ void tek440x_state::fpu_w(offs_t offset, u16 data)
1039
1068
m_mswoperand[m_operand] = data;
1040
1069
m_operand++;
1041
1070
break ;
1042
-
1043
- // select float or double
1071
+
1072
+ // start op, can be FPCALC or FPCONV...
1044
1073
case 6 :
1074
+ m_result = 0 ;
1045
1075
m_fpuselect = data;
1046
- if (data != FLOAT)
1047
- LOG (" fpu_w: DOUBLE not implemented\n " );
1048
1076
m_operand = 0 ;
1049
1077
break ;
1050
1078
case 7 :
1051
1079
break ;
1052
1080
}
1053
1081
}
1054
1082
1083
+ void tek440x_state::fpu_latch32_result (void *v)
1084
+ {
1085
+ m_result <<= 32 ;
1086
+ m_result |= *(uint32_t *)v;
1087
+ }
1088
+
1089
+ void tek440x_state::fpu_latch64_result (void *v)
1090
+ {
1091
+ m_result = *(uint64_t *)v;
1092
+ }
1093
+
1094
+ #define CASE_ENUM (C ) case C: opname = #C; break
1055
1095
1056
1096
u16 tek440x_state::fpu_r (offs_t offset)
1057
1097
{
1058
- // status check
1098
+ // status check; should pretend to be not-ready for a bit
1059
1099
if (offset == 4 )
1060
- return 0 ;
1100
+ {
1101
+ float af,bf;
1102
+ double ad,bd;
1103
+ int ai;
1104
+
1105
+ uint32_t v32;
1106
+ uint64_t v64;
1061
1107
1062
- // NB doing floating calc twice, once for low word read, again for high word read..
1063
-
1064
- unsigned int ai = (m_mswoperand[1 ] << 16 ) | (m_lswoperand[1 ]);
1065
- float a = *(float *)&ai;
1108
+ #ifdef DEBUG
1109
+ const char *opname;
1110
+ switch (m_lswoperand[0 ])
1111
+ {
1112
+ CASE_ENUM (FADD);
1113
+ CASE_ENUM (FSUB);
1114
+ CASE_ENUM (FMUL);
1115
+ CASE_ENUM (FDIV);
1116
+ CASE_ENUM (FCMP);
1117
+
1118
+ CASE_ENUM (FItoF);
1119
+ CASE_ENUM (FFtoIr);
1120
+ CASE_ENUM (FFtoIt);
1121
+ CASE_ENUM (FFtoIf);
1122
+ CASE_ENUM (FFtoD);
1123
+ CASE_ENUM (FDtoF);
1124
+
1125
+ CASE_ENUM (DADD);
1126
+ CASE_ENUM (DSUB);
1127
+ CASE_ENUM (DMUL);
1128
+ CASE_ENUM (DDIV);
1129
+ CASE_ENUM (DCMP);
1130
+
1131
+ CASE_ENUM (FItoD);
1132
+ CASE_ENUM (FDtoIr);
1133
+ CASE_ENUM (FDtoIt);
1134
+ CASE_ENUM (FDtoIf);
1135
+
1136
+ default :
1137
+ opname = " unknown" ;
1138
+ break ;
1139
+ }
1140
+ LOGMASKED (LOG_FPU," fpu_r: %s ************** %s \n " , m_fpuselect == FPCALC ? " FPCALC" : " FPCONV" , opname);
1141
+ #endif
1066
1142
1067
- unsigned int bi = (m_mswoperand[2 ] << 16 ) | (m_lswoperand[2 ]);
1068
- float b = *(float *)&bi;
1143
+ // assembling operands
1144
+ if (m_operand >= 2 ) // has at least 1 32-bit operands
1145
+ {
1146
+ v32 = (m_mswoperand[1 ] << 16 ) | (m_lswoperand[1 ]);
1147
+ ai = v32;
1148
+ af = *(float *)&v32;
1149
+ LOGMASKED (LOG_FPU," fpu_r: m_operand(%d) float(%f) int(%d)\n " , m_operand, af, ai);
1150
+
1151
+ if (m_operand >= 3 ) // has at least 2 32-bit operands or 1 64-bit operand
1152
+ {
1153
+ v32 = (m_mswoperand[2 ] << 16 ) | (m_lswoperand[2 ]);
1154
+ bf = *(float *)&v32;
1069
1155
1070
- LOG (" fpu_r: %04x %f %f\n " ,m_lswoperand[0 ], a,b);
1156
+ v64 = (((uint64_t )m_mswoperand[2 ]) << 48 ) | (((uint64_t )m_lswoperand[2 ])<<32 ) | (((uint64_t )m_mswoperand[1 ]) << 16 ) | (m_lswoperand[1 ]);
1157
+ ad = *(double *)&v64;
1071
1158
1072
- float c;
1073
- switch (m_lswoperand[0 ])
1074
- {
1075
- case FADD:
1076
- c = a + b;
1077
- break ;
1078
- case FSUB:
1079
- c = a - b;
1080
- break ;
1081
- case FMUL:
1082
- c = a * b;
1083
- break ;
1084
- case FDIV:
1085
- c = a / b;
1086
- break ;
1087
- default :
1088
- LOG (" fpu_r: unknown opcode 0x%04x\n " , m_lswoperand[0 ]);
1089
- }
1159
+ LOGMASKED (LOG_FPU," fpu_r: m_operand(%d) float(%f) float(%f) double(%lf) 0x%lx\n " , m_operand, af,bf, ad, v64);
1160
+ }
1161
+
1162
+ if (m_operand == 5 ) // has 2 64-bit operands
1163
+ {
1164
+ v64 = (((uint64_t )m_mswoperand[4 ]) << 48 ) | (((uint64_t )m_lswoperand[4 ])<<32 ) | (((uint64_t )m_mswoperand[3 ]) << 16 ) | (m_lswoperand[3 ]);
1165
+ bd = *(double *)&v64;
1166
+
1167
+ LOGMASKED (LOG_FPU," fpu_r: m_operand(%d) double(%lf) double(%lf)\n " , m_operand, ad,bd);
1168
+ }
1169
+ }
1170
+
1171
+ // execute the functionality
1172
+ int resulttype = FLOATRESULT;
1173
+ int ci;
1174
+ float cf;
1175
+ double cd;
1176
+ switch (m_lswoperand[0 ])
1177
+ {
1178
+ case FADD:
1179
+ cf = bf + af;
1180
+ fpu_latch32_result (&cf);
1181
+ resulttype = FLOATRESULT;
1182
+ break ;
1183
+ case FSUB:
1184
+ cf = bf - af;
1185
+ fpu_latch32_result (&cf);
1186
+ resulttype = FLOATRESULT;
1187
+ break ;
1188
+ case FMUL:
1189
+ cf = bf * af;
1190
+ fpu_latch32_result (&cf);
1191
+ resulttype = FLOATRESULT;
1192
+ break ;
1193
+ case FDIV:
1194
+ cf = bf / af;
1195
+ fpu_latch32_result (&cf);
1196
+ resulttype = FLOATRESULT;
1197
+ break ;
1198
+ case FCMP:
1199
+ ci = af > bf ? 1 : (af < bf ? -1 : 0 );
1200
+ fpu_latch32_result (&ci);
1201
+ resulttype = FLOATRESULT;
1202
+ break ;
1203
+
1204
+ case FNEG:
1205
+ cf = -af;
1206
+ fpu_latch32_result (&cf);
1207
+ resulttype = FLOATRESULT;
1208
+ break ;
1209
+ case FABS:
1210
+ cf = fabs (af);
1211
+ fpu_latch32_result (&cf);
1212
+ resulttype = FLOATRESULT;
1213
+ break ;
1214
+
1215
+ case FItoF:
1216
+ cf = (float )ai;
1217
+ fpu_latch32_result (&cf);
1218
+ resulttype = FLOATRESULT;
1219
+ break ;
1220
+ case FFtoIr:
1221
+ ci = (int )(af + 0 .5f );
1222
+ fpu_latch32_result (&ci);
1223
+ resulttype = INTRESULT;
1224
+ break ;
1225
+ case FFtoIt:
1226
+ ci = (int )(af);
1227
+ fpu_latch32_result (&ci);
1228
+ resulttype = INTRESULT;
1229
+ break ;
1230
+ case FFtoIf:
1231
+ ci = (int )floorf (af);
1232
+ fpu_latch32_result (&ci);
1233
+ resulttype = INTRESULT;
1234
+ break ;
1235
+
1236
+ case FFtoD:
1237
+ cd = (double )af;
1238
+ fpu_latch64_result (&cd);
1239
+ resulttype = DOUBLERESULT;
1240
+ break ;
1241
+ case FDtoF:
1242
+ cf = (float )ad;
1243
+ fpu_latch32_result (&cf);
1244
+ break ;
1245
+
1246
+ case DADD:
1247
+ cd = bd + ad;
1248
+ fpu_latch64_result (&cd);
1249
+ resulttype = DOUBLERESULT;
1250
+ break ;
1251
+ case DSUB:
1252
+ cd = bd - ad;
1253
+ fpu_latch64_result (&cd);
1254
+ resulttype = DOUBLERESULT;
1255
+ break ;
1256
+ case DMUL:
1257
+ cd = bd * ad;
1258
+ fpu_latch64_result (&cd);
1259
+ resulttype = DOUBLERESULT;
1260
+ break ;
1261
+ case DDIV:
1262
+ cd = bd / ad;
1263
+ fpu_latch64_result (&cd);
1264
+ resulttype = DOUBLERESULT;
1265
+ break ;
1266
+ case DCMP:
1267
+ ci = ad > bd ? 1 : (ad < bd ? -1 : 0 );
1268
+ fpu_latch32_result (&ci);
1269
+ resulttype = DOUBLERESULT;
1270
+ break ;
1271
+
1272
+ case DNEG:
1273
+ cd = -ad;
1274
+ fpu_latch64_result (&cd);
1275
+ resulttype = DOUBLERESULT;
1276
+ break ;
1277
+ case DABS:
1278
+ cd = fabs (ad);
1279
+ fpu_latch64_result (&cd);
1280
+ resulttype = DOUBLERESULT;
1281
+ break ;
1282
+
1283
+ case FItoD:
1284
+ cd = (double )ai;
1285
+ fpu_latch64_result (&cd);
1286
+ resulttype = DOUBLERESULT;
1287
+ break ;
1288
+ case FDtoIr:
1289
+ ci = (int )(ad + 0.5 );
1290
+ fpu_latch32_result (&ci);
1291
+ resulttype = DOUBLERESULT;
1292
+ break ;
1293
+ case FDtoIt:
1294
+ ci = (int )(ad);
1295
+ fpu_latch32_result (&ci);
1296
+ resulttype = DOUBLERESULT;
1297
+ break ;
1298
+ case FDtoIf:
1299
+ ci = (int )floor (ad);
1300
+ fpu_latch32_result (&ci);
1301
+ resulttype = DOUBLERESULT;
1302
+ break ;
1303
+
1304
+ default :
1305
+ LOGMASKED (LOG_FPU," fpu_r: unknown opcode 0x%04x\n " , m_lswoperand[0 ]);
1306
+ m_result = 0x4000 ;
1307
+ break ;
1308
+ }
1090
1309
1091
- unsigned int ci = *(unsigned int *)&c;
1310
+ switch (resulttype)
1311
+ {
1312
+ default :
1313
+ case FLOATRESULT:
1314
+ LOGMASKED (LOG_FPU," fpu_r: m_result = 0x%lx float(%f)\n " , m_result, cf);
1315
+ break ;
1316
+ case DOUBLERESULT:
1317
+ LOGMASKED (LOG_FPU," fpu_r: m_result = 0x%lx double(%lf)\n " , m_result, cd);
1318
+ break ;
1319
+ case INTRESULT:
1320
+ LOGMASKED (LOG_FPU," fpu_r: m_result = 0x%lx int(%d)\n " , m_result, ci);
1321
+ break ;
1322
+
1323
+ }
1324
+
1325
+ // always ready (bit15 clear)
1326
+ return 0 ;
1327
+ }
1328
+
1329
+ u16 result = 0 ;
1092
1330
switch (offset)
1093
1331
{
1094
1332
default :
1095
- return 0 ;
1096
-
1097
- case 2 :
1098
- return ci & 0xffff ;
1333
+ break ;
1099
1334
1335
+ // shift out result word at a time
1336
+ case 2 :
1100
1337
case 3 :
1101
- return (ci >> 16 ) & 0xffff ;
1102
-
1338
+ result = m_result & 0xffff ;
1339
+ m_result >>= 16 ;
1340
+ break ;
1103
1341
}
1342
+
1343
+ return result;
1104
1344
}
1105
1345
1106
1346
u16 tek440x_state::videoaddr_r (offs_t offset)
0 commit comments