1pub use self::decoder::*;
4mod decoder;
5
6pub use self::instruction::*;
7mod instruction;
8
9pub use self::segment::*;
10mod segment;
11
12pub use self::register::*;
13mod register;
14
15pub use self::flag::*;
16mod flag;
17
18pub use self::parameter::*;
19mod parameter;
20
21pub use self::op::*;
22mod op;
23
24pub use self::encoder::*;
25mod encoder;
26
27use std::{mem, u8};
28use std::num::Wrapping;
29use std::marker::PhantomData;
30
31use crate::gpu::GPU;
32use crate::interrupt;
33use crate::machine::Machine;
34use crate::memory::{MMU, MemoryAddress};
35
36const DEBUG_PARAMS_TOUCHING_STACK: bool = false;
38
39const DEBUG_STACK: bool = false;
41
42#[derive(Debug)]
43pub enum Exception {
44 DIV0 = 0, UD = 6, DF = 8, TS = 10, NP = 11, SS = 12, GP = 13, PF = 14, }
54
55pub struct CPU {
56 pub instruction_count: usize,
57 pub cycle_count: usize,
58
59 pub regs: RegisterState,
61
62 pub fatal_error: bool,
64
65 pub deterministic: bool,
67
68 pub decoder: Decoder,
69 pub clock_hz: usize,
70}
71
72impl CPU {
73 pub fn default() -> Self {
74 CPU {
75 instruction_count: 0,
76 cycle_count: 0,
77 regs: RegisterState::default(),
78 fatal_error: false,
79 deterministic: false,
80 decoder: Decoder::default(),
81 clock_hz: 5_000_000, }
83 }
84
85 pub fn deterministic() -> Self {
86 let mut res = Self::default();
87 res.deterministic = true;
88 res
89 }
90
91 pub fn get_r8(&self, r: R) -> u8 {
92 self.regs.get_r8(r)
93 }
94
95 pub fn set_r8(&mut self, r: R, val: u8) {
96 self.regs.set_r8(r, val);
97 }
98
99 pub fn get_r16(&self, r: R) -> u16 {
100 self.regs.get_r16(r)
101 }
102
103 pub fn set_r16(&mut self, r: R, val: u16) {
104 self.regs.set_r16(r, val);
105 }
106
107 pub fn get_r32(&self, r: R) -> u32 {
108 self.regs.get_r32(r)
109 }
110
111 pub fn set_r32(&mut self, r: R, val: u32) {
112 self.regs.set_r32(r, val);
113 }
114
115 pub fn exception(&mut self, which: &Exception, error: usize) {
116 println!("Exception {:?}, error {}", which, error);
123
124 }
126
127 pub fn cmp8(&mut self, dst: usize, src: usize) {
128 let res = (Wrapping(dst) - Wrapping(src)).0;
129
130 self.regs.flags.set_carry_u8(res);
132 self.regs.flags.set_overflow_sub_u8(res, src, dst);
133 self.regs.flags.set_sign_u8(res);
134 self.regs.flags.set_zero_u8(res);
135 self.regs.flags.set_adjust(res, src, dst);
136 self.regs.flags.set_parity(res);
137 }
138
139 pub fn cmp16(&mut self, dst: usize, src: usize) {
140 let res = (Wrapping(dst) - Wrapping(src)).0;
141
142 self.regs.flags.set_carry_u16(res);
144 self.regs.flags.set_overflow_sub_u16(res, src, dst);
145 self.regs.flags.set_sign_u16(res);
146 self.regs.flags.set_zero_u16(res);
147 self.regs.flags.set_adjust(res, src, dst);
148 self.regs.flags.set_parity(res);
149 }
150
151 pub fn cmp32(&mut self, dst: usize, src: usize) {
152 let res = (Wrapping(dst) - Wrapping(src)).0;
153
154 self.regs.flags.set_carry_u32(res);
156 self.regs.flags.set_overflow_sub_u32(res, src, dst);
157 self.regs.flags.set_sign_u32(res);
158 self.regs.flags.set_zero_u32(res);
159 self.regs.flags.set_adjust(res, src, dst);
160 self.regs.flags.set_parity(res);
161 }
162
163 pub fn push16(&mut self, mmu: &mut MMU, data: u16) {
164 let sp = (Wrapping(self.get_r16(R::SP)) - Wrapping(2)).0;
165 self.set_r16(R::SP, sp);
166 let ss = self.get_r16(R::SS);
167 if DEBUG_STACK {
168 println!("[{}] push16 {:04X} to {:04X}:{:04X}", self.get_memory_address(), data, ss, sp);
169 }
170 mmu.write_u16(ss, sp, data);
171 }
172
173 pub fn push32(&mut self, mmu: &mut MMU, data: u32) {
174 let sp = (Wrapping(self.get_r16(R::SP)) - Wrapping(4)).0;
175 self.set_r16(R::SP, sp);
176 let ss = self.get_r16(R::SS);
177 if DEBUG_STACK {
178 println!("[{}] push32 {:04X} to {:04X}:{:04X}", self.get_memory_address(), data, ss, sp);
179 }
180 mmu.write_u32(ss, sp, data);
181 }
182
183 pub fn pop16(&mut self, mmu: &mut MMU) -> u16 {
184 let ss = self.get_r16(R::SS);
185 let sp = self.get_r16(R::SP);
186 let data = mmu.read_u16(ss, self.get_r16(R::SP));
187 if DEBUG_STACK {
188 println!("[{}] pop16 {:04X} from {:04X}:{:04X}", self.get_memory_address(), data, ss, sp);
189 }
190 let sp = (Wrapping(sp) + Wrapping(2)).0;
191 self.set_r16(R::SP, sp);
192 data
193 }
194
195 pub fn pop32(&mut self, mmu: &mut MMU) -> u32 {
196 let ss = self.get_r16(R::SS);
197 let sp = self.get_r16(R::SP);
198 let data = mmu.read_u32(ss, sp);
199 if DEBUG_STACK {
200 println!("[{}] pop32 {:04X} from {:04X}:{:04X}", self.get_memory_address(), data, ss, sp);
201 }
202 let sp = (Wrapping(sp) + Wrapping(4)).0;
203 self.set_r16(R::SP, sp);
204 data
205 }
206
207 pub fn get_address(&self) -> u32 {
209 self.get_memory_address().value()
210 }
211
212 pub fn get_address_pair(&self) -> (u16, u16) {
214 (self.get_r16(R::CS), self.regs.ip)
215 }
216
217 pub fn get_memory_address(&self) -> MemoryAddress {
219 MemoryAddress::RealSegmentOffset(self.get_r16(R::CS), self.regs.ip)
220 }
221
222 fn read_u8(&mut self, mmu: &MMU) -> u8 {
223 let (seg, off) = self.get_address_pair();
224 let b = mmu.read_u8(seg, off);
225 self.regs.ip += 1;
226 b
227 }
228
229 fn read_u16(&mut self, mmu: &MMU) -> u16 {
230 let lo = self.read_u8(mmu);
231 let hi = self.read_u8(mmu);
232 u16::from(hi) << 8 | u16::from(lo)
233 }
234
235 fn read_s8(&mut self, mmu: &MMU) -> i8 {
236 self.read_u8(mmu) as i8
237 }
238
239 fn read_s16(&mut self, mmu: &MMU) -> i16 {
240 self.read_u16(mmu) as i16
241 }
242
243 fn read_rel8(&mut self, mmu: &MMU) -> u16 {
244 let val = self.read_u8(mmu) as i8;
245 (self.regs.ip as i16 + i16::from(val)) as u16
246 }
247
248 fn read_rel16(&mut self, mmu: &MMU) -> u16 {
249 let val = self.read_u16(mmu) as i16;
250 (self.regs.ip as i16 + val) as u16
251 }
252
253 fn get_amode_addr(&self, amode: &AMode) -> (u16, u16) {
255 match *amode {
256 AMode::BX => (self.get_r16(R::DS), self.get_r16(R::BX)),
257 AMode::BP => (self.get_r16(R::SS), self.get_r16(R::BP)),
258 AMode::SI => (self.get_r16(R::DS), self.get_r16(R::SI)),
259 AMode::DI => (self.get_r16(R::DS), self.get_r16(R::DI)),
260 AMode::BXSI => (self.get_r16(R::DS), self.get_r16(R::BX) + self.get_r16(R::SI)),
261 AMode::BXDI => (self.get_r16(R::DS), self.get_r16(R::BX) + self.get_r16(R::DI)),
262 AMode::BPSI => (self.get_r16(R::SS), self.get_r16(R::BP) + self.get_r16(R::SI)),
263 AMode::BPDI => (self.get_r16(R::SS), self.get_r16(R::BP) + self.get_r16(R::DI)),
264 _ => panic!("xxx"),
265 }
266 }
267
268 pub fn read_segment_selector(&self, mmu: &MMU, p: &Parameter) -> (u16, u16) {
270 let (segment, offset) = match *p {
271 Parameter::Ptr16(seg, imm) => (self.segment(seg), imm),
272 Parameter::Ptr16Amode(_, ref amode) => self.get_amode_addr(amode),
273 Parameter::Ptr16AmodeS8(_, ref amode, imms) => {
274 let (seg, off) = self.get_amode_addr(amode);
275 (seg, (i32::from(off) + i32::from(imms)) as u16)
276 }
277 _ => panic!("unhandled parameter {:?}", p),
284 };
285
286 let o_val = mmu.read_u16(segment, offset);
287 let s_val = mmu.read_u16(segment, offset + 2);
288 (s_val, o_val)
289 }
290
291 pub fn read_parameter_address(&mut self, p: &Parameter) -> usize {
293 match *p {
294 Parameter::Ptr16Amode(_, ref amode) => self.amode(amode),
295 Parameter::Ptr16AmodeS8(_, ref amode, imm) => (Wrapping(self.amode(amode)) + Wrapping(imm as usize)).0,
296 Parameter::Ptr16AmodeS16(_, ref amode, imm) => (Wrapping(self.amode(amode)) + Wrapping(imm as usize)).0,
297 Parameter::Ptr16(_, imm) => imm as usize,
298 _ => panic!("unhandled parameter: {:?} at {:06X}", p, self.get_address()),
299 }
300 }
301
302 pub fn read_parameter_imm(&self, p: &Parameter) -> usize {
303 match *p {
304 Parameter::Imm8(imm) => imm as usize,
305 Parameter::Imm16(imm) => imm as usize,
306 Parameter::ImmS8(imm) => imm as usize,
307 _ => panic!("read_parameter_imm only allows imm-type params: {:?}", p),
308 }
309 }
310
311 pub fn read_parameter_value(&mut self, mmu: &MMU, p: &Parameter) -> usize {
312 match *p {
313 Parameter::Imm8(imm) => imm as usize,
314 Parameter::Imm16(imm) => imm as usize,
315 Parameter::Imm32(imm) => imm as usize,
316 Parameter::ImmS8(imm) => imm as usize,
317 Parameter::Reg8(r) => self.get_r8(r) as usize,
318 Parameter::Reg16(r) => self.get_r16(r) as usize,
319 Parameter::Reg32(r) => self.get_r32(r) as usize,
320 Parameter::SReg16(sr) => self.get_r16(sr) as usize,
321 Parameter::Ptr8(seg, imm) => mmu.read_u8(self.segment(seg), imm) as usize,
322 Parameter::Ptr8Amode(seg, ref amode) => {
323 let seg = self.segment(seg);
324 let offset = self.amode(amode) as u16;
325 mmu.read_u8(seg, offset) as usize
326 }
327 Parameter::Ptr8AmodeS8(seg, ref amode, imm) => {
328 let seg = self.segment(seg);
329 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
330 mmu.read_u8(seg, offset) as usize
331 }
332 Parameter::Ptr8AmodeS16(seg, ref amode, imm) => {
333 let seg = self.segment(seg);
334 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
335 mmu.read_u8(seg, offset) as usize
336 }
337 Parameter::Ptr16(seg, imm) => mmu.read_u16(self.segment(seg), imm) as usize,
338 Parameter::Ptr16Amode(seg, ref amode) => {
339 let seg = self.segment(seg);
340 let offset = self.amode(amode) as u16;
341 mmu.read_u16(seg, offset) as usize
342 }
343 Parameter::Ptr16AmodeS8(seg, ref amode, imm) => {
344 let seg = self.segment(seg);
345 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
346 mmu.read_u16(seg, offset) as usize
347 }
348 Parameter::Ptr16AmodeS16(seg, ref amode, imm) => {
349 let seg = self.segment(seg);
350 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
351 mmu.read_u16(seg, offset) as usize
352 }
353 Parameter::Ptr32(seg, offset) => mmu.read_u32(self.segment(seg), offset) as usize,
354 Parameter::Ptr32Amode(seg, ref amode) => {
355 let seg = self.segment(seg);
356 let offset = self.amode(amode) as u16;
357 mmu.read_u32(seg, offset) as usize
358 }
359 Parameter::Ptr32AmodeS8(seg, ref amode, imm) => {
360 let seg = self.segment(seg);
361 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
362 mmu.read_u32(seg, offset) as usize
363 }
364 _ => {
365 let (seg, off) = self.get_address_pair();
366 panic!("unhandled parameter: {:?} at {:04X}:{:04X} ({:06X} flat)", p, seg, off, self.get_address());
367 },
368 }
369 }
370
371 pub fn write_parameter_u8(&mut self, mmu: &mut MMU, p: &Parameter, data: u8) {
372 match *p {
373 Parameter::Reg8(r) => self.set_r8(r, data),
374 Parameter::Ptr8(seg, offset) => {
375 let seg = self.segment(seg);
376 self.debug_write_u8(seg, offset, data);
377 mmu.write_u8(seg, offset, data);
378 }
379 Parameter::Ptr8Amode(seg, ref amode) => {
380 let seg = self.segment(seg);
381 let offset = self.amode(amode) as u16;
382 self.debug_write_u8(seg, offset, data);
383 mmu.write_u8(seg, offset, data);
384 }
385 Parameter::Ptr8AmodeS8(seg, ref amode, imm) => {
386 let seg = self.segment(seg);
387 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
388 self.debug_write_u8(seg, offset, data);
389 mmu.write_u8(seg, offset, data);
390 }
391 Parameter::Ptr8AmodeS16(seg, ref amode, imm) => {
392 let seg = self.segment(seg);
393 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
394 self.debug_write_u8(seg, offset, data);
395 mmu.write_u8(seg, offset, data);
396 }
397 _ => panic!("write_parameter_u8 unhandled type {:?} at {:06X}", p, self.get_address()),
398 }
399 }
400
401 pub fn write_parameter_u16(&mut self, mmu: &mut MMU, segment: Segment, p: &Parameter, data: u16) {
402 match *p {
403 Parameter::Reg16(r) |
404 Parameter::SReg16(r) => self.set_r16(r, data),
405 Parameter::Imm16(imm) => {
406 let seg = self.segment(segment);
407 self.debug_write_u16(seg, imm, data);
408 mmu.write_u16(seg, imm, data);
409 }
410 Parameter::Ptr16(seg, offset) => {
411 let seg = self.segment(seg);
412 self.debug_write_u16(seg, offset, data);
413 mmu.write_u16(seg, offset, data);
414 }
415 Parameter::Ptr16Amode(seg, ref amode) => {
416 let seg = self.segment(seg);
417 let offset = self.amode(amode) as u16;
418 self.debug_write_u16(seg, offset, data);
419 mmu.write_u16(seg, offset, data);
420 }
421 Parameter::Ptr16AmodeS8(seg, ref amode, imm) => {
422 let seg = self.segment(seg);
423 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
424 self.debug_write_u16(seg, offset, data);
425 mmu.write_u16(seg, offset, data);
426 }
427 Parameter::Ptr16AmodeS16(seg, ref amode, imm) => {
428 let seg = self.segment(seg);
429 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
430 self.debug_write_u16(seg, offset, data);
431 mmu.write_u16(seg, offset, data);
432 }
433 _ => panic!("unhandled type {:?} at {:06X}", p, self.get_address()),
434 }
435 }
436
437 pub fn write_parameter_u32(&mut self, mmu: &mut MMU, _segment: Segment, p: &Parameter, data: u32) {
438 match *p {
439 Parameter::Reg32(r) => self.set_r32(r, data),
440 Parameter::Ptr32(seg, offset) => {
441 let seg = self.segment(seg);
442 self.debug_write_u32(seg, offset, data);
443 mmu.write_u32(seg, offset, data);
444 }
445 Parameter::Ptr32Amode(seg, ref amode) => {
446 let seg = self.segment(seg);
447 let offset = self.amode(amode);
448 self.debug_write_u32(seg, offset as u16, data);
449 mmu.write_u32(seg, offset as u16, data);
450 }
451 Parameter::Ptr32AmodeS8(seg, ref amode, imm) => {
452 let seg = self.segment(seg);
453 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
454 self.debug_write_u32(seg, offset as u16, data);
455 mmu.write_u32(seg, offset, data);
456 }
457 Parameter::Ptr32AmodeS16(seg, ref amode, imm) => {
458 let seg = self.segment(seg);
459 let offset = (Wrapping(self.amode(amode) as u16) + Wrapping(imm as u16)).0;
460 self.debug_write_u32(seg, offset as u16, data);
461 mmu.write_u32(seg, offset, data);
462 }
463 _ => panic!("unhandled type {:?} at {:06X}", p, self.get_address()),
464 }
465 }
466
467 fn debug_write_u8(&self, seg: u16, off: u16, data: u8) {
468 if !DEBUG_PARAMS_TOUCHING_STACK {
469 return;
470 }
471 let pos = MemoryAddress::RealSegmentOffset(seg, off).value() as isize;
472 let stack = MemoryAddress::RealSegmentOffset(self.get_r16(R::SS), self.get_r16(R::SP));
473 let code = MemoryAddress::RealSegmentOffset(self.get_r16(R::CS), self.get_r16(R::IP));
474 let dist = (pos - stack.value() as isize).abs();
475 if dist < 256 {
476 println!("[{}] debug_write_u8 {:04X}:{:04X} = {:02X} ... stack {} (dist {})", code, seg, off, data, stack, dist);
478 }
479 }
480
481 fn debug_write_u16(&self, seg: u16, off: u16, data: u16) {
482 if !DEBUG_PARAMS_TOUCHING_STACK {
483 return;
484 }
485 let pos = MemoryAddress::RealSegmentOffset(seg, off).value() as isize;
486 let stack = MemoryAddress::RealSegmentOffset(self.get_r16(R::SS), self.get_r16(R::SP));
487 let code = MemoryAddress::RealSegmentOffset(self.get_r16(R::CS), self.get_r16(R::IP));
488 let dist = (pos - stack.value() as isize).abs();
489 if dist < 256 {
490 println!("[{}] debug_write_u16 {:04X}:{:04X} = {:04X} ... stack {} (dist {})", code, seg, off, data, stack, dist);
492 }
493 }
494
495 fn debug_write_u32(&self, seg: u16, off: u16, data: u32) {
496 if !DEBUG_PARAMS_TOUCHING_STACK {
497 return;
498 }
499 let pos = MemoryAddress::RealSegmentOffset(seg, off).value() as isize;
500 let stack = MemoryAddress::RealSegmentOffset(self.get_r16(R::SS), self.get_r16(R::SP));
501 let code = MemoryAddress::RealSegmentOffset(self.get_r16(R::CS), self.get_r16(R::IP));
502 let dist = (pos - stack.value() as isize).abs();
503 if dist < 256 {
504 println!("[{}] debug_write_u32 {:04X}:{:04X} = {:08X} ... stack {} (dist {})", code, seg, off, data, stack, dist);
506 }
507 }
508
509 pub fn segment(&self, seg: Segment) -> u16 {
511 self.get_r16(seg.as_register())
512 }
513
514 pub fn amode(&self, amode: &AMode) -> usize {
515 match *amode {
516 AMode::BXSI => (Wrapping(self.get_r16(R::BX)) + Wrapping(self.get_r16(R::SI))).0 as usize,
517 AMode::BXDI => (Wrapping(self.get_r16(R::BX)) + Wrapping(self.get_r16(R::DI))).0 as usize,
518 AMode::BPSI => (Wrapping(self.get_r16(R::BP)) + Wrapping(self.get_r16(R::SI))).0 as usize,
519 AMode::BPDI => (Wrapping(self.get_r16(R::BP)) + Wrapping(self.get_r16(R::DI))).0 as usize,
520 AMode::SI => self.get_r16(R::SI) as usize,
521 AMode::DI => self.get_r16(R::DI) as usize,
522 AMode::BP => self.get_r16(R::BP) as usize,
523 AMode::BX => self.get_r16(R::BX) as usize,
524
525 AMode::EAX => self.get_r32(R::EAX) as usize,
526 AMode::ECX => self.get_r32(R::ECX) as usize,
527 AMode::EDX => self.get_r32(R::EDX) as usize,
528 AMode::EBX => self.get_r32(R::EBX) as usize,
529 AMode::ESP => self.get_r32(R::ESP) as usize,
530 AMode::EBP => self.get_r32(R::EBP) as usize,
531 AMode::ESI => self.get_r32(R::ESI) as usize,
532 AMode::EDI => self.get_r32(R::EDI) as usize,
533 }
534 }
535
536 pub fn adjb(&mut self, param1: i8, param2: i8) {
538 if self.regs.flags.adjust || (self.get_r8(R::AL) & 0xf) > 9 {
539 let al = (i16::from(self.get_r8(R::AL)) + i16::from(param1)) as u8;
540 let ah = (i16::from(self.get_r8(R::AH)) + i16::from(param2)) as u8;
541 self.set_r8(R::AL, al);
542 self.set_r8(R::AH, ah);
543 self.regs.flags.adjust = true;
544 self.regs.flags.carry = true;
545 } else {
546 self.regs.flags.adjust = false;
547 self.regs.flags.carry = false;
548 }
549 let al = self.get_r8(R::AL);
550 self.set_r8(R::AL, al & 0x0F);
551 }
552
553 pub fn adj4(&mut self, param1: i16, param2: i16) {
555 let mut al = self.get_r8(R::AL);
556 if ((al & 0x0F) > 0x09) || self.regs.flags.adjust {
557 if (al > 0x99) || self.regs.flags.carry {
558 al = (i16::from(al) + param2) as u8;
559 self.regs.flags.carry = true;
560 } else {
561 self.regs.flags.carry = false;
562 }
563 al = (i16::from(al) + param1) as u8;
564 self.regs.flags.adjust = true;
565 } else {
566 if (al > 0x99) || self.regs.flags.carry {
567 al = (i16::from(al) + param2) as u8;
568 self.regs.flags.carry = true;
569 } else {
570 self.regs.flags.carry = false;
571 }
572 self.regs.flags.adjust = false;
573 }
574 self.set_r8(R::AL, al);
575 self.regs.flags.sign = al & 0x80 != 0;
576 self.regs.flags.zero = al == 0;
577 self.regs.flags.set_parity(al as usize);
578 }
579}