Skip to content

Commit 0771764

Browse files
author
Adam
committed
- ns32081 interface seems to work
- not sure about FCMP / DCMP return values.
1 parent 92be6f5 commit 0771764

File tree

1 file changed

+284
-44
lines changed

1 file changed

+284
-44
lines changed

src/mame/tektronix/tek440x.cpp

Lines changed: 284 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070

7171
#define LOG_GENERAL (1U << 0)
7272
#define LOG_MMU (1U << 1)
73+
#define LOG_FPU (1U << 2)
7374

7475
#define VERBOSE 1
7576
#include "logmacro.h"
@@ -565,6 +566,9 @@ class tek440x_state : public driver_device
565566
u8 mouse_r(offs_t offset);
566567
void mouse_w(u8 data);
567568
void led_w(u8 data);
569+
570+
void fpu_latch32_result(void *);
571+
void fpu_latch64_result(void *);
568572
u16 fpu_r(offs_t offset);
569573
void fpu_w(offs_t offset, u16 data);
570574
u16 videoaddr_r(offs_t offset);
@@ -645,6 +649,7 @@ class tek440x_state : public driver_device
645649
u16 m_operand;
646650
u16 m_lswoperand[5];
647651
u16 m_mswoperand[5];
652+
uint64_t m_result;
648653

649654
u16 m_videoaddr[4];
650655
u8 m_videocntl;
@@ -1006,25 +1011,49 @@ void tek440x_state::mapcntl_w(u8 data)
10061011

10071012
}
10081013

1014+
enum {FLOATRESULT=0, DOUBLERESULT=1, INTRESULT=2};
10091015

10101016
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,
10131034

10141035
FADD = 0x0142,
10151036
FSUB = 0x1142,
10161037
FMUL = 0x3142,
10171038
FDIV = 0x2142,
10181039
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
10231050

10241051
};
10251052

10261053
void tek440x_state::fpu_w(offs_t offset, u16 data)
10271054
{
1055+
LOG("fpu_w: %08x <= 0x%04x\n", offset, data);
1056+
10281057
switch(offset)
10291058
{
10301059
default:
@@ -1039,68 +1068,279 @@ void tek440x_state::fpu_w(offs_t offset, u16 data)
10391068
m_mswoperand[m_operand] = data;
10401069
m_operand++;
10411070
break;
1042-
1043-
// select float or double
1071+
1072+
// start op, can be FPCALC or FPCONV...
10441073
case 6:
1074+
m_result = 0;
10451075
m_fpuselect = data;
1046-
if (data != FLOAT)
1047-
LOG("fpu_w: DOUBLE not implemented\n");
10481076
m_operand = 0;
10491077
break;
10501078
case 7:
10511079
break;
10521080
}
10531081
}
10541082

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
10551095

10561096
u16 tek440x_state::fpu_r(offs_t offset)
10571097
{
1058-
// status check
1098+
// status check; should pretend to be not-ready for a bit
10591099
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;
10611107

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
10661142

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;
10691155

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;
10711158

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+
}
10901309

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;
10921330
switch(offset)
10931331
{
10941332
default:
1095-
return 0;
1096-
1097-
case 2:
1098-
return ci & 0xffff;
1333+
break;
10991334

1335+
// shift out result word at a time
1336+
case 2:
11001337
case 3:
1101-
return (ci >> 16) & 0xffff;
1102-
1338+
result = m_result & 0xffff;
1339+
m_result >>= 16;
1340+
break;
11031341
}
1342+
1343+
return result;
11041344
}
11051345

11061346
u16 tek440x_state::videoaddr_r(offs_t offset)

0 commit comments

Comments
 (0)