Guest User

Untitled

a guest
Jun 4th, 2020
312
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 97.86 KB | None | 0 0
  1.  
  2. ;FOLD Defines
  3. UnimpInteger EQU 61*4 ;unimplemented integer instruction
  4. IllegalInst EQU 4*4 ;illegal instruction vector
  5. BusError EQU 2*4 ;the bus error handler
  6. DivisionByZero EQU 5*4
  7. CheckError EQU 6*4
  8. ;ENDFOLD
  9.  
  10. ;===============================================================
  11.  
  12. * include work:devpac/include30/include/exec/resident.i
  13.  
  14. machine mc68020
  15.  
  16. ;===============================================================
  17.  
  18. ; Resident TAG Structure
  19.  
  20. _Resident:
  21. dc.w $4afc ; RT_MATCHWORD
  22. dc.l _Resident ; RT_MATCHTAG
  23. dc.l _ResidentEnd ; RT_ENDSKIP
  24. dc.b 0 ; RT_FLAGS
  25. dc.b 1 ; RT_VERSION
  26. dc.b 0 ; RT_TYPE
  27. dc.b -120 ; RT_PRI
  28. dc.l my_RT_NAME ; RT_NAME
  29. dc.l my_RT_IDSTRING ; RT_IDSTRING
  30. dc.l my_RT_INIT ; RT_INIT
  31. _ResidentEnd
  32.  
  33. ; We want first instruction to be at $E00100
  34.  
  35. ds.b 212
  36.  
  37. ;===============================================================
  38.  
  39. section resident_code,code
  40.  
  41.  
  42. ; The resident code section starts here
  43. ;FOLD EmulationVector
  44. ;*****************************************************************
  45. ;** EmulationVector **
  46. ;** This is the entry point for the software emulation vector **
  47. ;*****************************************************************
  48. ; Offsets relative to the a7-world of the exception stack frame
  49. exc_d0 EQU 0
  50. exc_a0 EQU 8*4
  51. exc_sp EQU exc_a0+7*4
  52. exc_frameptr EQU exc_sp+4 ;pointer to the exception frame.
  53. exc_sr EQU exc_frameptr+4
  54. exc_pc EQU exc_sr+2
  55. exc_oldsr EQU exc_frameptr+8+4
  56. exc_oldpc EQU exc_oldsr+2
  57. exc_originalsp EQU exc_oldpc+4
  58. EmulationVector:
  59. subq.l #8,a7 ;headroom the user may overwrite
  60. subq.l #8,a7 ;keep for a7, and for the position of the stack frame
  61. movem.l d0-d7/a0-a6,-(a7)
  62. move.l a7,a5 ;get pointer to exception record
  63. move.w exc_oldsr(a5),d0 ;get the SR
  64. move.l usp,a0 ;get A7
  65. move.l exc_oldpc(a5),a1 ;get the PC
  66. btst #13,d0 ;check whether we came in here as supervisor
  67. beq.s .isuser
  68. lea exc_originalsp(a5),a0 ;this is the value of a7 without the stack frame
  69. .isuser:
  70. move.l a0,exc_sp(a5)
  71. move.w d0,exc_sr(a5) ;relocate the status register to make room on the stack
  72. move.l a1,exc_pc(a5) ;relocate the PC to make room on the stack frame
  73.  
  74. ; now read the instruction to be implemented
  75. move.l a1,a4 ;save the PC in a4, the instruction has already been read
  76. bsr ReadProgramWord
  77.  
  78. move.w d0,d1 ;keep the instruction
  79. lea LineVectors,a0
  80. rol.w #6,d1 ;get the line
  81. and.w #%111100,d1
  82. move.l (a0,d1.w),a0 ;call into the line handler
  83. jsr (a0)
  84.  
  85. move.l a4,exc_pc(a5) ;restore the PC
  86. btst #5,exc_sr(a5) ;do we need to reload usp?
  87. bne.s .issuper
  88. move.l exc_sp(a5),a0 ;user stack pointer
  89. lea exc_originalsp(a5),a1 ;supervisor stack frame
  90. move.l a0,usp
  91. bra.s .restorestack
  92. .issuper:
  93. move.l exc_sp(a5),a1 ;this becomes the super SP
  94. .restorestack:
  95. move.l exc_pc(a5),-(a1) ;push the PC on the stack
  96. move.w exc_sr(a5),-(a1) ;push the SR on the stack
  97. move.l a1,exc_frameptr(a5) ;keep the frame pointer
  98. movem.l (a7)+,d0-d7/a0-a6 ;
  99. addq.l #4,a7 ;the USP/SP we do not care about
  100. move.l (a7)+,a7 ;but the stack frame we do
  101. rte ;and continue.
  102. ;ENDFOLD
  103. ;FOLD GenerateException
  104. ;*****************************************************************
  105. ;** GenerateException **
  106. ;** Abort the execution and jump to the Os exception vector **
  107. ;** in d0 **
  108. ;*****************************************************************
  109. GenerateException:
  110. lea exc_originalsp(a5),a0 ;stack frame needs to go here.
  111. move.l d0,-(a0) ;create an exception frame that
  112. move.w exc_sr(a5),-(a0) ;jumps into the illegal instruction exception
  113. move.l a0,exc_frameptr(a5)
  114. move.l a5,a7 ;restore the stack frame, dispose the rest of the stack
  115. ;leave the PC unchanged and the SP as well.
  116. movem.l (a7)+,d0-d7/a0-a6 ;
  117. addq.l #4,a7 ;the USP/SP we do not care about
  118. move.l (a7)+,a7 ;but the stack frame we do
  119. rte
  120. ;ENDFOLD
  121. ;FOLD GenerateIllegalInstructionException
  122. ;*****************************************************************
  123. ;** GenerateIllegalInstructionException **
  124. ;** Create an illegal instruction exception **
  125. ;*****************************************************************
  126. GenerateIllegalInstructionException:
  127. NoSuchInstruction:
  128. ;there is currently no vbr, nothing, thus just get the vector "as is".
  129. move.l IllegalInst,d0
  130. bra.s GenerateException
  131. ;ENDFOLD
  132. ;FOLD GenerateDivisionByZero
  133. ;*****************************************************************
  134. ;** GenerateDivisionByZero **
  135. ;** Create a division by zero exception **
  136. ;*****************************************************************
  137. GenerateDivisionByZero:
  138. ;there is currently no vbr, nothing, thus just get the vector "as is".
  139. move.l DivisionByZero,d0
  140. bra.s GenerateException
  141. ;ENDFOLD
  142. ;FOLD GenerateChkException
  143. ;*****************************************************************
  144. ;** GenerateCheckException **
  145. ;** Create an exception due to CHK or CHK2 **
  146. ;*****************************************************************
  147. GenerateChkException:
  148. ;there is currently no vbr, nothing, thus just get the vector "as is".
  149. move.l CheckError,d0
  150. bra.s GenerateException
  151. ;ENDFOLD
  152. ;FOLD CreateBusError
  153. ;*****************************************************************
  154. ;** GenerateBusError **
  155. ;*****************************************************************
  156. GenerateBusError:
  157. move.l BusError,d0
  158. bra.s GenerateException
  159. ;ENDFOLD
  160. ;FOLD CheckPage
  161. ;*****************************************************************
  162. ;** CheckPage **
  163. ;** Check whether the data word of size d1 (1,2,4) at *a0 **
  164. ;** can be accessed without creating a page fault. Generate **
  165. ;** a bus error if so. Otherwise, return. **
  166. ;*****************************************************************
  167. CheckPage:
  168. ;there is currently nothing we can do.
  169. rts
  170. ;ENDFOLD
  171. ;FOLD ReadProgramWord
  172. ;*****************************************************************
  173. ;** ReadProgramWord **
  174. ;** Read an instruction from the emulated PC passed in at a0 **
  175. ;** does not adjust PC (still to be done by the caller) **
  176. ;** Returns the instruction in d0.
  177. ;*****************************************************************
  178. ReadProgramWord:
  179. ;; There is currently no MMU here, no chance to get anything
  180. ;; corrupted, thus just make a plain move.
  181. ;; Even moves is not supported, so don't bother.
  182. move.w (a4)+,d0
  183. rts
  184. ;ENDFOLD
  185. ;FOLD ReadMemory
  186. ;*****************************************************************
  187. ;** Read a data of the size in d1 from the user address space **
  188. ;** at *a0 and return it in d0. **
  189. ;*****************************************************************
  190. ReadMemory:
  191. subq.b #1,d1
  192. lsl.b #2,d1
  193. jmp .read(pc,d1.w)
  194. .read:
  195. move.b (a0),d0
  196. rts
  197. move.w (a0),d0
  198. rts
  199. nop
  200. nop
  201. move.l (a0),d0
  202. .exitr:
  203. rts
  204. ;ENDFOLD
  205. ;FOLD WriteMemory
  206. ;*****************************************************************
  207. ;** Write data d0 of the size in d1 to the user address space **
  208. ;** at *a0. **
  209. ;*****************************************************************
  210. WriteMemory:
  211. subq.b #1,d1
  212. lsl.b #2,d1
  213. jmp .write(pc,d1.w)
  214. .write:
  215. move.b d0,(a0)
  216. rts
  217. move.w d0,(a0)
  218. rts
  219. nop
  220. nop
  221. move.l d0,(a0)
  222. .exitw:
  223. rts
  224. ;ENDFOLD
  225. ;FOLD ReadMemoryByte
  226. ;*****************************************************************
  227. ;** Read a single byte from the user address space *a0 **
  228. ;** and return it in d0. **
  229. ;*****************************************************************
  230. ReadMemoryByte:
  231. move.b (a0),d0
  232. rts
  233. ;ENDFOLD
  234. ;FOLD WriteMemoryByte
  235. ;*****************************************************************
  236. ;** Write a single byte in d0 to user space memory at *a0 **
  237. ;*****************************************************************
  238. WriteMemoryByte:
  239. move.b d0,(a0)
  240. rts
  241. ;ENDFOLD
  242. ;FOLD GetEffectiveEA
  243. ;*****************************************************************
  244. ;** GetEffectiveEA **
  245. ;** Return the effective address in a0, bits 0..5. **
  246. ;** The size of a data unit in bytes (1,2,4) is in d1 **
  247. ;** Note that this returns the address, not the value within **
  248. ;** and hence does not take dx and ax as addressing modes **
  249. ;** ditto immediate **
  250. ;** If the size is zero, predecrement and postincrement **
  251. ;** are disallowed, too. **
  252. ;** Returns the ea in a0 **
  253. ;*****************************************************************
  254. GetEffectiveEA:
  255. MOVE.L d2,-(sp)
  256. move.b d0,d2
  257. lea EADecode,a0
  258. lsr.b #3,d2
  259. and.w #%111,d0 ;this is the register
  260. and.w #%111,d2 ;this is the mode
  261. lsl.w #2,d0
  262. lsl.w #2,d2 ;four byte entries, each
  263. move.l (a0,d2.w),a0
  264. jsr (a0)
  265. MOVE.L (sp)+,D2
  266. rts
  267. DecodeDx:
  268. DecodeAx:
  269. jmp GenerateIllegalInstructionException(pc)
  270. DecodeIndirect:
  271. move.l exc_a0(a5,d0.w),a0
  272. rts
  273. DecodePostIncrement:
  274. tst.b d1 ;do we have a size?
  275. beq.s DecodeAx
  276. cmp.w #7*4,d0 ;indirect with A7
  277. bne.s .regularI
  278. cmp.b #1,d1 ;byte access
  279. bne.s .regularI
  280. add.b d1,d1 ;rather increment by 2 than 1.
  281. .regularI:
  282. move.l exc_a0(a5,d0.w),a0
  283. add.l d1,exc_a0(a5,d0.w)
  284. rts
  285.  
  286. DecodePredecrement:
  287. tst.b d1
  288. beq.s DecodeAx ;do we have a size?
  289. cmp.w #7*4,d0 ;indirect with A7
  290. bne.s .regularD
  291. cmp.b #1,d1 ;byte access
  292. bne.s .regularD
  293. add.b d1,d1 ;rather decrement by 2 than 1.
  294. .regularD:
  295. sub.l d1,exc_a0(a5,d0.w)
  296. move.l exc_a0(a5,d0.w),a0
  297. rts
  298. DecodeDisplacement:
  299. move.l d0,d2 ;keep register
  300. bsr ReadProgramWord
  301. ext.l d0
  302. move.l exc_a0(a5,d2.w),a0
  303. add.l d0,a0 ;add the effective adress
  304. rts
  305. DecodeIndexed:
  306. move.l d0,d2
  307. bsr ReadProgramWord
  308. move.l exc_a0(a5,d2.w),a0 ;get the base register
  309. move.w d0,d1 ;keep the extension word
  310. ext.w d1 ;use the inner displacement
  311. ext.l d1 ;extend fully
  312. add.l d1,a0 ;add to the address
  313. btst #8,d0 ;full extension word is not supported by phoenix
  314. bne.s .illegal
  315. move.w d0,d1 ;restore the extension word
  316. rol.w #4,d1 ;move the index register to bits 3..0
  317. and.w #15,d1
  318. rol.w #7,d0 ;extract the scale
  319. lsl.w #2,d1 ;get register offset
  320. move.l exc_d0(a5,d1.w),d1 ;index register is now in d1
  321. btst #2,d0 ;word sized or long sized?
  322. bne.s .islong
  323. ext.l d1 ;extend the index to long
  324. .islong:
  325. and.b #3,d0
  326. lsl.l d0,d1 ;implement scaling
  327. add.l d1,a0
  328. rts
  329. .illegal:
  330. jmp GenerateIllegalInstructionException(pc)
  331. DecodeMisc:
  332. lea EAMiscDecode,a0
  333. move.l (a0,d0.w),a0
  334. jmp (a0)
  335. AbsoluteWord:
  336. bsr ReadProgramWord
  337. ext.l d0
  338. move.l d0,a0
  339. AbsoluteLong:
  340. bsr ReadProgramWord
  341. move.l d0,d2
  342. bsr ReadProgramWord
  343. swap d2
  344. move.w d0,d2
  345. move.l d2,a0
  346. rts
  347. PCDisplacement:
  348. bsr ReadProgramWord
  349. lea -2(a4,d0.w),a0 ;the PC is the PC of the extension word.
  350. rts
  351. PCIndexed:
  352. bsr ReadProgramWord
  353. move.w d0,d1 ;keep the extension word
  354. ext.w d1 ;use the inner displacement
  355. lea -2(a4,d1.w),a0 ;the PC is the PC of the extension word.
  356. btst #8,d0 ;full extension word is not supported by phoenix
  357. bne.s .illegalPCI
  358. move.w d0,d1 ;restore the extension word
  359. ror.l #4,d1 ;move the index register to bits 3..0
  360. and.w #15,d1
  361. rol.w #7,d0 ;extract the scale
  362. lsl.w #2,d1 ;get register offset
  363. move.l exc_d0(a5,d1.w),d1 ;index register is now in d1
  364. btst #2,d0 ;word sized or long sized?
  365. bne.s .islongPCI
  366. ext.l d1 ;extend the index to long
  367. .islongPCI:
  368. and.b #3,d0
  369. lsl.l d0,d1 ;implement scaling
  370. add.l d1,a0
  371. rts
  372. .illegalPCI:
  373. Illegal:
  374. Immediate:
  375. jmp GenerateIllegalInstructionException(pc)
  376. ;ENDFOLD
  377. ;FOLD LoadDataEA
  378. ;*****************************************************************
  379. ;** LoadDataEA **
  380. ;** Return the effective address in d0, bits 0..5. **
  381. ;** The size of a data unit in bytes (1,2,4) is in d1 **
  382. ;** this returns the contents of the EA (not the EA itself) **
  383. ;** in d0 **
  384. ;*****************************************************************
  385. LoadDataEA:
  386. MOVEM.L d2,-(SP)
  387. move.l d1,d2 ;keep the size
  388. move.l d0,d1
  389. and.w #%111000,d1
  390. bne.s .notregisterL
  391. ; here: data register direct
  392. lsl.w #2,d0
  393. and.w #%11100,d0
  394. move.l exc_d0(a5,d0.w),d0
  395. bra.s .exitL
  396. .notregisterL:
  397. cmp.w #%111000,d1 ;misc, probably immediate?
  398. bne.s .regularL
  399. move.l d0,d1
  400. and.w #%000111,d1 ;immediate?
  401. cmp.w #%000100,d1
  402. bne.s .regularL ;otherwise, Abs.W,Abs.L or (PC)
  403. bsr ReadProgramWord
  404. cmp.b #2,d2 ;reading a word?
  405. beq.s .exitL ;if so, we just got it in d0.
  406. cmp.b #1,d2 ;or reading a byte?
  407. beq.s .exitL ;also ok
  408. move.l d0,d2 ;this is the high-word
  409. bsr ReadProgramWord
  410. swap d2
  411. move.w d0,d2
  412. move.l d2,d0 ;and this the result
  413. bra.s .exitL
  414. .regularL:
  415. bsr GetEffectiveEA ;load the EA into a0
  416. move.l d2,d1
  417. bsr ReadMemory ;get the data
  418. .exitL:
  419. MOVEM.L (sp)+,D2
  420. rts
  421. ;ENDFOLD
  422. ;FOLD LineCVector
  423. ;*****************************************************************
  424. ;** Emulation code for line C instructions **
  425. ;** The instruction is in d0 **
  426. ;*****************************************************************
  427. LineCVector:
  428. move.w d0,d1
  429. and.w #%1111000111111000,d1 ;mask out register values
  430. cmp.w #%1100000100000000,d1 ;ABCD register-based
  431. beq ABCDRegister
  432. cmp.w #%1100000100001000,d1 ;ABCD memory-based
  433. beq ABCDMemory
  434. jmp NoSuchInstruction(pc)
  435. ;ENDFOLD
  436. ;FOLD Line8Vector
  437. ;*****************************************************************
  438. ;** Emulation code for line 8 instructions **
  439. ;** The instruction is in d0 **
  440. ;*****************************************************************
  441. Line8Vector:
  442. move.w d0,d1
  443. and.w #%1111000111111000,d1 ;mask out register values
  444. cmp.w #%1000000100000000,d1 ;ABCD register-based
  445. beq SBCDRegister
  446. cmp.w #%1000000100001000,d1 ;ABCD memory-based
  447. beq SBCDMemory
  448. cmp.w #%1000000101000000,d1
  449. beq PackRegister
  450. cmp.w #%1000000101001000,d1
  451. beq PackMemory
  452. cmp.w #%1000000110000000,d1
  453. beq UnpackRegister
  454. cmp.w #%1000000110001000,d1
  455. beq UnpackMemory
  456. jmp NoSuchInstruction(pc)
  457. ;ENDFOLD
  458. ;FOLD ABCDRegister
  459. ;*****************************************************************
  460. ;** Emulation code for ABCD register to register **
  461. ;** The instruction is in d0 **
  462. ;** the register file in a5 **
  463. ;*****************************************************************
  464. ABCDRegister:
  465. MOVEM.L d2/a2,-(sp)
  466. move.w d0,d1
  467. and.w #%111,d1 ;get the source register
  468. move.w d0,d2 ;keep instruction
  469. lsl.w #2,d1
  470. move.l exc_d0(a5,d1.w),d1 ;source register
  471. move.w d2,d0
  472. lsr.w #9-2,d0
  473. and.w #%11100,d0
  474. lea exc_d0(a5,d0.w),a2
  475. move.l (a2),d0 ;destination register
  476. bsr ABCDCore ;execute core code
  477. move.l (a2),d1
  478. clr.b d1
  479. move.b d0,d1
  480. move.l d1,(a2) ;insert target
  481. MOVEM.L (sp)+,D2/a2
  482. rts
  483. ;ENDFOLD
  484. ;FOLD ABCDMemory
  485. ;*****************************************************************
  486. ;** Emulation code for ABCD memory to memory **
  487. ;** The instruction is in d0 **
  488. ;** the register file in a5 **
  489. ;*****************************************************************
  490. ABCDMemory:
  491. MOVEM.L d2-d3/a2,-(sp)
  492. move.w d0,d1
  493. and.w #%111,d1 ;get the source register
  494. move.w d0,d2 ;keep instruction
  495. lsl.w #2,d1
  496. move.l exc_a0(a5,d1.w),a0 ;source register
  497. cmp.b #7*4,d1
  498. bne.s .nosp
  499. subq.l #1,a0
  500. .nosp:
  501. subq.l #1,a0
  502. move.l a0,exc_a0(a5,d1.w)
  503. bsr ReadMemoryByte ;read from RAM
  504. move.l d0,d3 ;keep source
  505.  
  506. move.w d2,d0 ;get instruction again
  507. lsr.w #9-2,d0
  508. and.w #%11100,d0
  509. move.l exc_a0(a5,d0.w),a0 ;destination register
  510. cmp.b #7*4,d0
  511. bne.s .nosp2
  512. subq.l #1,a0
  513. .nosp2:
  514. subq.l #1,a0
  515. move.l a0,a2 ;keep for target
  516. move.l a0,exc_a0(a5,d0.w)
  517. bsr ReadMemoryByte
  518.  
  519. move.l d3,d1 ;restore source to d1
  520. bsr ABCDCore ;execute core code
  521. move.l a2,a0 ;restore the address
  522. bsr WriteMemoryByte ;and place in the destination
  523.  
  524. MOVEM.L (sp)+,d2-d3/a2
  525. rts
  526. ;ENDFOLD
  527. ;FOLD ABCDCore
  528. ;*****************************************************************
  529. ;** ABCDCore **
  530. ;** Implement the ABCD instruction, source=d1,dest=d0 **
  531. ;** with d0<-d0+d1+X (in BCD) **
  532. ;*****************************************************************
  533. ABCDCore:
  534. MOVEM.L d2-d3,-(sp)
  535. move.b d0,d2
  536. move.b d1,d3
  537. and.b #$f,d0
  538. and.b #$f0,d2
  539. and.b #$f,d1
  540. and.b #$f0,d3 ;extract nibbles
  541. btst #4,1+exc_sr(a5) ;is X set?
  542. beq.s .nox
  543. add.b #1,d1 ;if so, include the carry from last time
  544. .nox:
  545. and.b #%01110,1+exc_sr(a5) ;clear X and C
  546. add.b d1,d0
  547. cmp.b #9,d0 ;decimal half-carry?
  548. bls.s .nocarry
  549. add.b #6,d0 ;decimal adjust
  550. add.b #$10,d3 ;carry over into source
  551. bcc.s .nocarry
  552. or.b #%10001,1+exc_sr(a5) ;set carry
  553. .nocarry:
  554. add.b d3,d2 ;add the high-nibbles
  555. bls.s .nocarryhi
  556. add.b #$60,d2 ;again decimal adjust
  557. or.b #%10001,1+exc_sr(a5) ;set carry
  558. .nocarryhi:
  559. and.b #$0f,d0 ;mask low-nibble
  560. and.b #$f0,d2 ;mask hi-nibble
  561. or.b d2,d0 ;put back together
  562. beq.s .noclrz
  563. bclr #2,1+exc_sr(a5) ;clear Z
  564. .noclrz:
  565. movem.l (sp)+,d2-d3
  566. rts
  567. ;ENDFOLD
  568. ;FOLD SBCDRegister
  569. ;*****************************************************************
  570. ;** Emulation code for SBCD register to register **
  571. ;** The instruction is in d0 **
  572. ;** the register file in a5 **
  573. ;*****************************************************************
  574. SBCDRegister:
  575. MOVEM.L d2/a2,-(sp)
  576. move.w d0,d1
  577. and.w #%111,d1 ;get the source register
  578. move.w d0,d2 ;keep instruction
  579. lsl.w #2,d1
  580. move.l exc_d0(a5,d1.w),d1 ;source register
  581. move.w d2,d0
  582. lsr.w #9-2,d0
  583. and.w #%11100,d0
  584. lea exc_d0(a5,d0.w),a2
  585. move.l (a2),d0 ;destination register
  586. bsr SBCDCore ;execute core code
  587. move.l (a2),d1
  588. clr.b d1
  589. move.b d0,d1
  590. move.l d1,(a2) ;insert target
  591. ;??? clz
  592. MOVEM.L (sp)+,d2/a2
  593. rts
  594. ;ENDFOLD
  595. ;FOLD SBCDMemory
  596. ;*****************************************************************
  597. ;** Emulation code for SBCD memory to memory **
  598. ;** The instruction is in d0 **
  599. ;** the register file in a5 **
  600. ;*****************************************************************
  601. SBCDMemory:
  602. MOVEM.L d2-d3/a2,-(sp)
  603. move.w d0,d1
  604. and.w #%111,d1 ;get the source register
  605. move.w d0,d2 ;keep instruction
  606. lsl.w #2,d1
  607. move.l exc_a0(a5,d1.w),a0 ;source register
  608. cmp.b #7*4,d1
  609. bne.s .nospS
  610. subq.l #1,a0
  611. .nospS:
  612. subq.l #1,a0
  613. move.l a0,exc_a0(a5,d1.w)
  614. bsr ReadMemoryByte ;read from RAM
  615. move.l d0,d3 ;keep source
  616.  
  617. move.w d2,d0 ;get instruction again
  618. lsr.w #9-2,d0
  619. and.w #%11100,d0
  620. move.l exc_a0(a5,d0.w),a0 ;destination register
  621. cmp.b #7*4,d0
  622. bne.s .nospS2
  623. subq.l #1,a0
  624. .nospS2:
  625. subq.l #1,a0
  626. move.l a0,a2 ;keep for target
  627. move.l a0,exc_a0(a5,d0.w)
  628. bsr ReadMemoryByte
  629.  
  630. move.l d3,d1 ;restore source to d1
  631. bsr SBCDCore ;execute core code
  632. move.l a2,a0 ;restore the address
  633. bsr WriteMemoryByte ;and place in the destination
  634. .exitS:
  635. MOVEM.L (sp)+,d2-d3/a2
  636. rts
  637. ;ENDFOLD
  638. ;FOLD SBCDCore
  639. ;*****************************************************************
  640. ;** SBCDCore **
  641. ;** Implement the ABCD instruction, source=d1,dest=d0 **
  642. ;** with d0<-d0+d1 (in BCD) **
  643. ;*****************************************************************
  644. SBCDCore:
  645. MOVEM.L d2-d3,-(sp)
  646. move.b d0,d2
  647. move.b d1,d3
  648. and.b #$f,d0
  649. and.b #$f0,d2
  650. and.b #$f,d1
  651. and.b #$f0,d3 ;extract nibbles
  652. btst #4,1+exc_sr(a5) ;is X set?
  653. beq.s .noxS
  654. add.b #1,d1
  655. .noxS:
  656. and.b #%01110,1+exc_sr(a5) ;clear X and C
  657. sub.b d1,d0
  658. bcc.s .nocarryS ;decimal half-carry?
  659. sub.b #6,d0 ;decimal adjust
  660. add.b #$10,d3 ;carry over into source
  661. .nocarryS:
  662. sub.b d3,d2 ;add the high-nibbles
  663. bcc.s .nocarryhiS
  664. sub.b #$60,d2 ;again decimal adjust
  665. or.b #%10001,1+exc_sr(a5) ;set carry
  666. .nocarryhiS:
  667. and.b #$0f,d0 ;mask low-nibble
  668. and.b #$f0,d2 ;mask hi-nibble
  669. or.b d2,d0 ;put back together
  670. beq.s .noclrzS
  671. bclr #2,1+exc_sr(a5) ;clear Z
  672. .noclrzS:
  673. MOVEM.L (sp)+,d2-d3
  674. rts
  675. ;ENDFOLD
  676. ;FOLD PackRegister
  677. ;*****************************************************************
  678. ;** Emulation code for the PACK instruction **
  679. ;** This is the register-based version **
  680. ;** The instruction is in d0 **
  681. ;*****************************************************************
  682. PackRegister:
  683. MOVEM.L d3/a2,-(sp)
  684. move.l d0,d1
  685. lsl.w #2,d1
  686. lsr.w #9-2,d0
  687. and.w #%11100,d1
  688. and.w #%11100,d0
  689. move.l exc_d0(a5,d1.w),d3 ;get source register dx
  690. lea exc_d0(a5,d0.w),a2 ;get destination register dy
  691. bsr ReadProgramWord ;get extension word
  692. add.w d0,d3 ;add to the source register
  693. move.w d3,d1
  694. and.b #%1111,d3 ;extact bits 0-3 from the result
  695. lsr.w #4,d1 ;move bits 11-8 to 7-4
  696. and.b #%11110000,d1 ;mask out other bits
  697. or.b d3,d1 ;merge LSBs
  698. move.b d1,3(a2) ;place into the lower bit of the destination
  699. MOVEM.L (sp)+,D3/A2
  700. rts
  701. ;ENDFOLD
  702. ;FOLD PackMemory
  703. ;*****************************************************************
  704. ;** Emulation code for the PACK instruction **
  705. ;** This is the memory-based version **
  706. ;** The instruction is in d0 **
  707. ;*****************************************************************
  708. PackMemory:
  709. MOVEM.L d2/a2-a3,-(sp)
  710. move.l d0,d1
  711. lsl.w #2,d1
  712. lsr.w #9-2,d0
  713. and.w #%11100,d1
  714. and.w #%11100,d0
  715. lea exc_a0(a5,d1.w),a2 ;get source register dx
  716. lea exc_a0(a5,d0.w),a3 ;get destination register dy
  717. bsr ReadProgramWord ;get extension word
  718. lea exc_sp(a5),a0
  719. move.l d0,d2 ;keep me
  720.  
  721. cmp.l a3,a0 ;are we working on the SP?
  722. bne.s .singleP
  723. subq.l #1,(a3)
  724. .singleP:
  725. subq.l #2,(a2)
  726. subq.l #1,(a3) ;pre-decrement addresses
  727.  
  728. move.l (a2),a0 ;get source
  729. moveq #2,d1
  730. bsr ReadMemory ;get data
  731. add.w d0,d2 ;add to extension word
  732. move.w d2,d0
  733. and.b #%1111,d2 ;extact bits 0-3 from the result
  734. lsr.w #4,d0 ;move bits 11-8 to 7-4
  735. and.b #%11110000,d0 ;mask out other bits
  736. or.b d2,d0 ;merge LSBs
  737. move.l (a3),a0
  738. bsr WriteMemoryByte
  739.  
  740. MOVEM.L d2/a2-a3,-(sp)
  741. rts
  742. ;ENDFOLD
  743. ;FOLD UnpackRegister
  744. ;*****************************************************************
  745. ;** Emulation code for the UNPACK instruction **
  746. ;** This is the register-based version **
  747. ;** The instruction is in d0 **
  748. ;*****************************************************************
  749. UnpackRegister:
  750. MOVEM.L d3/a2,-(sp)
  751. move.l d0,d1
  752. lsl.w #2,d1
  753. lsr.w #9-2,d0
  754. and.w #%11100,d1
  755. and.w #%11100,d0
  756. move.l exc_d0(a5,d1.w),d3 ;get source register dx
  757. lea exc_d0(a5,d0.w),a2 ;get destination register dy
  758. bsr ReadProgramWord ;get extension word
  759. move.w d3,d1 ;keep source again
  760. lsl.w #4,d1
  761. and.w #$0f,d3 ;low order bits
  762. and.w #$0f00,d1 ;upper bits
  763. or.w d3,d1 ;merge together
  764. add.w d0,d1 ;add adjustment word
  765. move.w d1,2(a2) ;place into the lower 16 bits
  766. MOVEM.L (sp)+,d3/a2
  767. rts
  768. ;ENDFOLD
  769. ;FOLD UnpackMemory
  770. ;*****************************************************************
  771. ;** Emulation code for the UNPACK instruction **
  772. ;** This is the memory-based version **
  773. ;** The instruction is in d0 **
  774. ;*****************************************************************
  775. UnpackMemory:
  776. MOVEM.L d2/a2-a3,-(sp)
  777. move.l d0,d1
  778. lsl.w #2,d1
  779. lsr.w #9-2,d0
  780. and.w #%11100,d1
  781. and.w #%11100,d0
  782. lea exc_a0(a5,d1.w),a2 ;get source register dx
  783. lea exc_a0(a5,d0.w),a3 ;get destination register dy
  784. bsr ReadProgramWord ;get extension word
  785. lea exc_sp(a5),a0
  786. move.l d0,d2 ;keep me
  787.  
  788. cmp.l a2,a0 ;are we working on the SP?
  789. bne.s .singleU
  790. subq.l #1,(a2)
  791. .singleU:
  792. subq.l #2,(a3) ;two bytes from the target
  793. subq.l #1,(a2) ;one byte from the source
  794.  
  795. move.l (a2),a0
  796. bsr ReadMemoryByte ;get source
  797. move.w d0,d1 ;keep source again
  798. lsl.w #4,d1
  799. and.w #$0f,d0 ;low order bits
  800. and.w #$0f00,d1 ;upper bits
  801. or.w d1,d0 ;merge together
  802. add.w d2,d0 ;add adjustment word
  803.  
  804. moveq #2,d1
  805. move.l (a3),a0
  806. bsr WriteMemory
  807.  
  808. MOVEM.L (sp)+,d2/a2-a3
  809. rts
  810. ;ENDFOLD
  811. ;FOLD Line4Vector
  812. ;*****************************************************************
  813. ;** Emulation code for line 4 instructions **
  814. ;** The instruction is in d0 **
  815. ;*****************************************************************
  816. Line4Vector:
  817. move.w d0,d1
  818. and.w #%1111111111000000,d1 ;mask out register values
  819. cmp.w #%0100100000000000,d1 ;NBCD?
  820. beq NBCDea
  821. move.w d0,d1
  822. and.w #%1111111111000000,d1
  823. cmp.w #%0100110000000000,d1 ;mulu.l/muls.l
  824. beq MULU
  825. cmp.w #%0100110001000000,d1 ;divu.l/divs.l
  826. beq DIVU
  827. jmp NoSuchInstruction(pc)
  828. ;ENDFOLD
  829. ;FOLD NBCDea
  830. ;*****************************************************************
  831. ;** Emulation code for NBCD **
  832. ;** The instruction is in d0 **
  833. ;*****************************************************************
  834. NBCDea:
  835. MOVEM.L a2,-(sp)
  836. move.w d0,d1
  837. and.w #%111000,d1 ;is it data register?
  838. beq.s .registerN ;if so, handle this manually
  839. cmp.w #%001000,d1 ;is it address register?
  840. beq.s .illegalN ;Ax is illegal
  841. cmp.w #%111000,d1 ;generic mode?
  842. bne.s .nbcgenericN
  843. move.w d0,d1
  844. and.w #%000111,d1 ;only Abs.W and Abs.L are valid here.
  845. cmp.w #%000001,d1
  846. bhi.s .illegalN
  847. .nbcgenericN: ;here an EA operation
  848. moveq #1,d1 ;operand size is one byte
  849. bsr GetEffectiveEA ;load EA->a0
  850. move.b (a0),d1 ;get the source
  851. moveq #0,d0 ;destination is zero
  852. move.l a0,a2 ;save EA
  853. bsr SBCDCore
  854. move.b d0,(a2) ;save result back
  855. bra.s .exitN
  856. .registerN:
  857. and.w #%000111,d0 ;extract the register value
  858. lsl.w #2,d0
  859. lea exc_d0(a5,d0.w),a2
  860. move.l (a2),d1 ;get the register value
  861. moveq #0,d0 ;subtract from zero
  862. bsr SBCDCore
  863. move.l (a2),d1
  864. clr.b d1
  865. move.b d0,d1
  866. move.l d1,(a2) ;done
  867. .exitN:
  868. MOVEM.l (sp)+,A2
  869. rts
  870. .illegalN:
  871. jmp NoSuchInstruction(pc)
  872. ;ENDFOLD
  873. ;FOLD MULU/MULS
  874. ;*****************************************************************
  875. ;** Emulation code for MULU and MULS as 32x32->64 **
  876. ;** The instruction is in d0 **
  877. ;*****************************************************************
  878. MULU:
  879. MOVEM.L d2-d3/a2-a3,-(sp)
  880. move.l d0,d2 ;keep it
  881. bsr ReadProgramWord ;this comes with an extension word
  882. move.l d0,d1
  883. and.w #%1000011111111000,d1
  884. move.l d0,d3 ;keep it for the signed/unsigned flag in bit 11
  885. cmp.w #%0000010000000000,d1 ;only 32x32->64 handled here.
  886. bne.s .illegalM
  887. move.l d0,d1
  888. and.w #%00111,d0
  889. rol.w #4+2,d1 ;register dlow->d1
  890. lsl.w #2,d0 ;register dhigh->d0
  891. and.w #%11100,d1
  892. lea exc_d0(a5,d0.w),a3 ;high
  893. lea exc_d0(a5,d1.w),a2 ;low
  894. move.l d2,d0
  895. moveq #4,d1 ;size is LONG
  896. bsr LoadDataEA ;load the ea from a data source
  897. move.l (a2),d2 ;read the low-registerw
  898. btst #11,d3 ;signed or unsigned?
  899. beq.s .unsignedM
  900.  
  901. moveq #0,d3
  902. tst.l d2
  903. bpl.s .ispos1M
  904. not.b d3
  905. neg.l d2
  906. .ispos1M:
  907. tst.l d0
  908. bpl.s .ispos2M
  909. not.b d3
  910. neg.l d0
  911. .ispos2M:
  912. bsr.s MultiplyKernel
  913.  
  914. tst.b d3 ;take the negative again?
  915. beq.s .haveresultM
  916. neg.l d0
  917. negx.l d1 ;invert lo,hi
  918. bra.s .haveresultM
  919.  
  920. .unsignedM:
  921. bsr.s MultiplyKernel
  922. ;result is now in d0,d1
  923. .haveresultM:
  924. move.l d0,(a2)
  925. and.b #%10000,1+exc_sr(a5) ;clear C,V,Z,N
  926. move.l d1,(a3) ;set the result
  927. bpl.s .nonegM
  928. bset #3,1+exc_sr(a5) ;set N if negative
  929. .nonegM:
  930. or.l d1,d0 ;zero?
  931. bne.s .notzeroM
  932. bset #2,1+exc_sr(a5) ;set Z
  933. .notzeroM:
  934. MOVEM.L (sp)+,d2-d3/a2-a3
  935. rts
  936. .illegalM:
  937. jmp NoSuchInstruction(pc)
  938. ;ENDFOLD
  939. ;FOLD MultiplyKernel
  940. ;*************************************************
  941. ;** MultiplyKernel **
  942. ;** multiply d0*d2 -> d1:d0 (hi in d1) **
  943. ;** this is only unsigned **
  944. ;*************************************************
  945. MultiplyKernel:
  946. MOVEM.L d2/d6-d7,-(sp)
  947.  
  948. move.l d2,d7 ;# md in %d7
  949. move.l d0,d6 ;# mr in %d6
  950. move.l d0,d1 ;# mr in %d5
  951. swap d6 ;# hi(mr) in lo %d6
  952. swap d7 ;# hi(md) in lo %d7
  953.  
  954. ;# complete necessary multiplies:
  955. mulu.w d2,d0 ;# [1] lo(mr) * lo(md)
  956. mulu.w d6,d2 ;# [2] hi(mr) * lo(md)
  957. mulu.w d7,d1 ;# [3] lo(mr) * hi(md)
  958. mulu.w d7,d6 ;# [4] hi(mr) * hi(md)
  959.  
  960. ;# add lo portions of [2],[3] to hi portion of [1].
  961. ;# add carries produced from these adds to [4].
  962. ;# lo([1]) is the final lo 16 bits of the result.
  963. clr.l d7 ;# load %d7 w/ zero value
  964. swap d0 ;# hi([1]) <==> lo([1])
  965. add.w d2,d0 ;# hi([1]) + lo([2])
  966. addx.l d7,d6 ;# [4] + carry
  967. add.w d1,d0 ;# hi([1]) + lo([3])
  968. addx.l d7,d6 ;# [4] + carry
  969. swap d0 ;# lo([1]) <==> hi([1])
  970.  
  971. ;# lo portions of [2],[3] have been added in to final result.
  972. ;# now, clear lo, put hi in lo reg, and add to [4]
  973. clr.w d2 ;# clear lo([2])
  974. clr.w d1 ;# clear hi([3])
  975. swap d2 ;# hi([2]) in lo %d4
  976. swap d1 ;# hi([3]) in lo %d5
  977. add.l d2,d1 ;# [4] + hi([2])
  978. add.l d6,d1 ;# [4] + hi([3])
  979.  
  980. MOVEM.l (sp)+,d2/d6-d7
  981. rts
  982. ;ENDFOLD
  983. ;FOLD DIVU/DIVS
  984. ;*****************************************************************
  985. ;** Emulation code for DIVU and DIVS as 64/32->32 **
  986. ;** The instruction is in d0 **
  987. ;*****************************************************************
  988. DIVU:
  989. MOVEM.L d2-d3/a2-a3,-(sp)
  990. move.l d0,d2 ;keep it
  991. bsr ReadProgramWord ;this comes with an extension word
  992. move.l d0,d1
  993. and.w #%1000011111111000,d1
  994. move.l d0,d3 ;keep it for the signed/unsigned flag in bit 11
  995. cmp.w #%0000010000000000,d1 ;only 32x32->64 handled here.
  996. bne.s .illegalDU
  997. move.l d0,d1
  998. and.w #%00111,d0
  999. rol.w #4+2,d1 ;register dlow->d1
  1000. lsl.w #2,d0 ;register dhigh->d0
  1001. and.w #%11100,d1
  1002. lea exc_d0(a5,d0.w),a3 ;high
  1003. lea exc_d0(a5,d1.w),a2 ;low
  1004. move.l d2,d0
  1005. moveq #4,d1 ;size is LONG
  1006. bsr LoadDataEA ;load the ea from a data source
  1007.  
  1008. move.l d0,d2 ;quotient
  1009. move.l (a3),d1 ;get high
  1010. move.l (a2),d0 ;get low
  1011. btst #11,d3 ;signed or unsigned?
  1012. beq.s .unsignedDU
  1013.  
  1014. ;here signed division
  1015. bsr.s DivsCode
  1016. bra.s .ddoneDU
  1017. .unsignedDU:
  1018. bsr DivuCode
  1019. .ddoneDU:
  1020. ;result is now in d0,d1 with remainder in d1 and quotient in d0
  1021. ;condition codes are already set by the above kernel.
  1022. move.l d1,(a3) ;reminder
  1023. move.l d0,(a2) ;quotient (only this is returned if a2=a3)
  1024.  
  1025. MOVEM.L (sp)+,d2-d3/a2-a3
  1026. rts
  1027. .illegalDU:
  1028. jmp NoSuchInstruction(pc)
  1029. ;ENDFOLD
  1030. ;FOLD DivsCode
  1031. ;*************************************************
  1032. ;** DivsCode **
  1033. ;** divide signed **
  1034. ;** Divide d1:d0 (hi,lo) by d2, signed **
  1035. ;** return the result in d0 (quotient) and **
  1036. ;** d1 (remainder) **
  1037. ;*************************************************
  1038. DivsCode:
  1039. MOVEM.L d3-d7/a2-a4/a6,-(sp)
  1040.  
  1041. moveq #0,d3 ;sign flag
  1042. moveq #0,d4 ;dividend sign flag
  1043. move.l d0,a3
  1044. move.l d1,a4 ;keep destination
  1045.  
  1046. move.l d2,d7 ;<0?
  1047. beq .divzDS
  1048. bpl.s .ispositiveDS
  1049. not.b d3 ;set inversion flag
  1050. neg.l d7 ;invert me for unsigned divsion
  1051. .ispositiveDS:
  1052. tst.l d1 ;negative?
  1053. slt.b d4 ;save sign of dividend
  1054. bpl.s .postwoDS
  1055. not.b d3
  1056. neg.l d0
  1057. negx.l d1 ;negate d1:d0
  1058. .postwoDS:
  1059. move.l d3,a6 ;keep me: total sign
  1060. move.l d4,a2 ;keep me: NDIVIDEND
  1061.  
  1062. move.l d0,d6 ;lo
  1063. move.l d1,d5 ;hi
  1064.  
  1065. ;tst.l d5 ;# is (hi(dividend) == 0)
  1066. bne.s .dnormaldivideDS ;# no, so try it the long way
  1067.  
  1068. tst.l d6 ;# is (lo(dividend) == 0), too
  1069. beq.s .ddoneDS ;# yes, so (dividend == 0)
  1070.  
  1071. cmp.l d6,d7 ;# is (divisor <= lo(dividend))
  1072. bls.s .d32bitdivideDS ;# yes, so use 32 bit divide
  1073.  
  1074. exg d5,d6 ;# q = 0, r = dividend
  1075. bra.s .divfinishDS ;# can't divide, we're done.
  1076.  
  1077. .d32bitdivideDS:
  1078. ; machine mc68020
  1079. divul.l d7,d5:d6 ;# it's only a 32/32 bit div!
  1080. ; machine mc68000
  1081. bra.s .divfinishDS
  1082.  
  1083. .dnormaldivideDS:
  1084. ;# last special case:
  1085. ;# - is hi(dividend) >= divisor ? if yes, then overflow
  1086. cmp.l d5,d7
  1087. bls.s .ddovfDS ;# answer won't fit in 32 bits
  1088.  
  1089. bsr Divide64by32
  1090.  
  1091. .divfinishDS:
  1092. move.l a2,d0 ;remainder has the same sign as dividend
  1093. beq.s .dccDS
  1094. neg.l d5
  1095. .dccDS
  1096. move.l a6,d1 ;total sign is postive?
  1097. beq.s .dqposDS
  1098.  
  1099. ;# 0x80000000 is the largest number representable as a 32-bit negative
  1100. ;# number. the negative of 0x80000000 is 0x80000000.
  1101. cmpi.l #$80000000,d6 ;# will (-quot) fit in 32 bits?
  1102. bhi.s .ddovfDS
  1103.  
  1104. neg.l d6 ;# make (-quot) 2's comp
  1105. bra.s .ddoneDS
  1106.  
  1107. .dqposDS:
  1108. btst #$1f,d6 ;# will (+quot) fit in 32 bits?
  1109. bne.b .ddovfDS
  1110.  
  1111. .ddoneDS:
  1112. ;# at this point, result is normal so ccodes are set based on result.
  1113. and.b #%10001,1+exc_sr(a5) ;clear N,Z,V
  1114. move.l a2,d2 ;get ccr
  1115. move.l d5,d1 ;set remainder
  1116. move.l d6,d0 ;set quotient
  1117. bne.s .notzeroDS
  1118. bset #2,1+exc_sr(a5) ;set Z flag (does not change N)
  1119. .notzeroDS:
  1120. bpl.s .exitDS
  1121. bset #3,1+exc_sr(a5)
  1122. bra.s .exitDS
  1123. ;**
  1124. ;** overflow case is here
  1125. ;**
  1126. .ddovfDS:
  1127. move.l a3,d0
  1128. move.l a4,d1 ;restore destination (remain unaffected)
  1129. bset #1,1+exc_sr(a5) ;set OV bit.
  1130. bclr #0,1+exc_sr(a5) ;clear carry.
  1131. .exitDS:
  1132. MOVEM.L (sp)+,d3-d7/a2-a4/a6
  1133. rts
  1134. .divzDS:
  1135. jmp GenerateDivisionByZero(pc)
  1136. ;ENDFOLD
  1137. ;FOLD DivuCode
  1138. ;*************************************************
  1139. ;** DivuCode **
  1140. ;** divide unsigned **
  1141. ;** divide the 64-bit word d1:d0 (hi,lo) by d2 **
  1142. ;** return quotient in d0, remainder in d1 **
  1143. ;*************************************************
  1144. DivuCode:
  1145. MOVEM.L d3-d7/a2-a4,-(sp)
  1146.  
  1147. move.l d0,a3
  1148. move.l d1,a4 ;keep destination
  1149.  
  1150. move.l d2,d7 ;->d7
  1151. beq.s .divzDUC
  1152. move.l d0,d6 ;lo
  1153. move.l d1,d5 ;hi
  1154.  
  1155. ;tst.l d5 ;# is (hi(dividend) == 0)
  1156. bne.s .dnormaldivideDUC ;# no, so try it the long way
  1157.  
  1158. tst.l d6 ;# is (lo(dividend) == 0), too
  1159. beq.s .ddoneDUC ;# yes, so (dividend == 0)
  1160.  
  1161. cmp.l d6,d7 ;# is (divisor <= lo(dividend))
  1162. bls.s .d32bitdivideDUC ;# yes, so use 32 bit divide
  1163.  
  1164. exg d5,d6 ;# q = 0, r = dividend
  1165. bra.s .ddoneDUC ;# can't divide, we're done.
  1166.  
  1167. .d32bitdivideDUC:
  1168. ; machine mc68020
  1169. divul.l d7,d5:d6 ;# it's only a 32/32 bit div!
  1170. ; machine mc68000
  1171. bra.s .ddoneDUC
  1172.  
  1173. .dnormaldivideDUC:
  1174. ;# last special case:
  1175. ;# - is hi(dividend) >= divisor ? if yes, then overflow
  1176. cmp.l d5,d7
  1177. bls.b .ddovfDUC ;# answer won't fit in 32 bits
  1178.  
  1179. bsr.s Divide64by32
  1180.  
  1181. .ddoneDUC:
  1182. and.b #%10001,1+exc_sr(a5) ;clear N,Z,V
  1183. move.l a2,d2 ;get ccr
  1184. move.l d5,d1 ;set remainder
  1185. move.l d6,d0 ;set quotient
  1186. bne.s .notzeroDUC
  1187. bset #2,1+exc_sr(a5) ;set Z flag (does not change N)
  1188. .notzeroDUC:
  1189. bpl.s .exitDUC
  1190. bset #3,1+exc_sr(a5)
  1191. bra.s .exitDUC
  1192. .ddovfDUC:
  1193. move.l a3,d0
  1194. move.l a4,d1 ;restore destination (remain unaffected)
  1195. bset #1,1+exc_sr(a5) ;set overflow bit.
  1196. bclr #0,1+exc_sr(a5) ;clear carry
  1197. .exitDUC
  1198. MOVEM.L (sp)+,d3-d7/a2-a4
  1199. rts
  1200. .divzDUC:
  1201. jmp GenerateDivisionByZero(pc)
  1202. ;ENDFOLD
  1203. ;FOLD Divide64by32
  1204. ;########################################################################
  1205. ;# This routine uses the 'classical' Algorithm D from Donald Knuth's #
  1206. ;# Art of Computer Programming, vol II, Seminumerical Algorithms. #
  1207. ;# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, #
  1208. ;# where U,V are words of the quadword dividend and longword divisor, #
  1209. ;# and U1, V1 are the most significant words. #
  1210. ;# #
  1211. ;# The most sig. longword of the 64 bit dividend must be in d5, least #
  1212. ;# in d6. The divisor must be in d7, and the #
  1213. ;# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). #
  1214. ;# The quotient is returned in d6, remainder in d5, unless the #
  1215. ;# v (overflow) bit is set in the saved ccr. If overflow, the dividend #
  1216. ;# is unchanged. #
  1217. ;# modifies all data registers #
  1218. ;########################################################################
  1219. Divide64by32:
  1220. ;# if the divisor msw is 0, use simpler algorithm then the full blown
  1221. ;# one at ddknuth:
  1222.  
  1223. cmpi.l #$ffff,d7
  1224. bhi.b .ddknuth ;# go use D. Knuth algorithm
  1225.  
  1226. ;# Since the divisor is only a word (and larger than the mslw of the dividend),
  1227. ;# a simpler algorithm may be used :
  1228. ;# In the general case, four quotient words would be created by
  1229. ;# dividing the divisor word into each dividend word. In this case,
  1230. ;# the first two quotient words must be zero, or overflow would occur.
  1231. ;# Since we already checked this case above, we can treat the most significant
  1232. ;# longword of the dividend as (0) remainder (see Knuth) and merely complete
  1233. ;# the last two divisions to get a quotient longword and word remainder:
  1234.  
  1235. moveq #0,d1
  1236. swap d5 ;# same as r*b if previous step rqd
  1237. swap d6 ;# get u3 to lsw position
  1238. move.w d6,d5 ;# rb + u3
  1239.  
  1240. divu.w d7,d5
  1241.  
  1242. move.w d5,d1 ;# first quotient word
  1243. swap d6 ;# get u4
  1244. move.w d6,d5 ;# rb + u4
  1245.  
  1246. divu.w d7,d5
  1247.  
  1248. swap d1
  1249. move.w d5,d1 ;# 2nd quotient 'digit'
  1250. clr.w d5
  1251. swap d5 ;# now remainder
  1252. move.l d1,d6 ;# and quotient
  1253.  
  1254. rts
  1255.  
  1256. .ddknuth:
  1257. ;# In this algorithm, the divisor is treated as a 2 digit (word) number
  1258. ;# which is divided into a 3 digit (word) dividend to get one quotient
  1259. ;# digit (word). After subtraction, the dividend is shifted and the
  1260. ;# process repeated. Before beginning, the divisor and quotient are
  1261. ;# 'normalized' so that the process of estimating the quotient digit
  1262. ;# will yield verifiably correct results..
  1263.  
  1264. moveq #0,d4 ;all the flags in d4
  1265. .ddnchk:
  1266. tst.l d7
  1267. bmi.b .ddnormalized
  1268. ;??? do
  1269. addq.l #$1,d4 ;count in d4
  1270. lsl.l #$1,d6 ;# shift u4,u3 with overflow to u2
  1271. roxl.l #$1,d5 ;# shift u1,u2
  1272. lsl.l #$1,d7 ;# shift the divisor
  1273. ;??? while.s pl
  1274.  
  1275. swap d4 ;keep lo-word free
  1276.  
  1277. .ddnormalized:
  1278. ;# Now calculate an estimate of the quotient words (msw first, then lsw).
  1279. ;# The comments use subscripts for the first quotient digit determination.
  1280. move.l d7,d3 ;# divisor
  1281. move.l d5,d2 ;# dividend mslw
  1282. swap d3
  1283. swap d2
  1284. move.w #$ffff,d1 ;# use max trial quotient word
  1285. cmp.w d3,d2 ;# V1 = U1 ?
  1286. beq.b .ddadj0
  1287.  
  1288. move.l d5,d1
  1289. divu.w d3,d1 ;# use quotient of mslw/msw
  1290. .ddadj0:
  1291.  
  1292. ;# now test the trial quotient and adjust. This step plus the
  1293. ;# normalization assures (according to Knuth) that the trial
  1294. ;# quotient will be at worst 2 too large.
  1295. ;# NOTE: We do not perform step D3 here. This is not required, as
  1296. ;# D4 is sufficient for adjusting a quotient that has been guessed
  1297. ;# "too large". At most, it can be off by two (easy to prove).
  1298.  
  1299. move.l d7,d2 ;V1V2->d2
  1300. ;#
  1301. ;# at this stage, d1 is scaled by 1<<16. Evaluate the 32x32 product d1'0xd7->d2(hi),d3(lo)
  1302. ;# d0,d2,d3,d6 are scratches
  1303. ;#
  1304. move.l d7,d0 ;V1V2->d0
  1305. swap d2 ;get hi of d7 = V1
  1306. mulu.w d1,d0 ;V2*q: scaled by 2^16, must be split in higher/lower pair
  1307. mulu.w d1,d2 ;V1*q: the upper 32 bit = V1*q, must be scaled by 2^32
  1308. move.l d0,d3 ;get lo
  1309. clr.w d0 ;clear lo
  1310. swap d3 ;part of it
  1311. swap d0 ;swap: scale by 2^16: This must be added to hi
  1312. clr.w d3 ;shift up by 16
  1313. add.l d0,d2 ;add to hi
  1314.  
  1315. sub.l d3,d6
  1316. subx.l d2,d5 ;# subtract double precision
  1317. bcc .dd2nd ;# no carry, do next quotient digit
  1318.  
  1319. ;# need to add back divisor longword to current ms 3 digits of dividend
  1320. ;# - according to Knuth, this is done only 2 out of 65536 times for random
  1321. ;# divisor, dividend selection.
  1322. ;
  1323. ;# thor: computations show that this loop is run at most twice.
  1324. ;# this is better than knuth in this specific case because we
  1325. ;# avoid the multiplications in D3 and this step here (D4) is
  1326. ;# only addition.
  1327. ;#
  1328. move.l d7,d3
  1329. move.l d7,d2 ;add V1V20 back to U1U2U3U4
  1330. swap d3
  1331. clr.w d2
  1332. clr.w d3
  1333. swap d2 ;# %d3 now ls word of divisor
  1334.  
  1335. ;??? do
  1336. subq.l #$1,d1 ;# q is one too large
  1337. add.l d3,d6 ;# aligned with 3rd word of dividend
  1338. addx.l d2,d5
  1339. ;??? while.s cc ;# until we're positive again
  1340. .dd2nd:
  1341. tst.l d4
  1342. bmi.b .ddremain
  1343.  
  1344. ;# first quotient digit now correct. store digit and shift the
  1345. ;# (subtracted) dividend
  1346. move.w d1,d4 ;keep hi-quotient
  1347. swap d5
  1348. swap d6
  1349. move.w d6,d5
  1350. clr.w d6 ;shift remainder up by 16 bits
  1351. bset #31,d4 ;second digit
  1352. bra.s .ddnormalized
  1353. .ddremain:
  1354. ;# add 2nd word to quotient, get the remainder.
  1355. swap d1
  1356. move.w d4,d1 ;get result of previous division
  1357. swap d1 ;restore order
  1358. swap d4 ;restore normalization counter
  1359.  
  1360. ;# shift down one word/digit to renormalize remainder.
  1361. move.w d5,d6
  1362. swap d6
  1363. swap d5
  1364. clr.l d7
  1365. move.b d4,d7
  1366. beq.b .ddrn
  1367. subq.l #$1,d7 ;# set for loop count
  1368. .ddnlp:
  1369. lsr.l #$1,d5 ;# shift into %d6
  1370. roxr.l #$1,d6
  1371. dbf d7,.ddnlp
  1372. .ddrn:
  1373. move.l d6,d5 ;# remainder
  1374. move.l d1,d6
  1375.  
  1376. rts
  1377. ;ENDFOLD
  1378. ;FOLD Line0Vector
  1379. ;*****************************************************************
  1380. ;** Emulation code for line 0 instructions **
  1381. ;** The instruction is in d0 **
  1382. ;*****************************************************************
  1383. Line0Vector:
  1384. move.w d0,d1
  1385. and.w #%1111000100111000,d1
  1386. cmp.w #%0000000100001000,d1
  1387. beq MOVEPea
  1388. move.w d0,d1
  1389. and.w #%1111100111000000,d1
  1390. cmp.w #%0000000011000000,d1
  1391. beq CMP2ea
  1392. move.w d0,d1
  1393. and.w #%1111110111111111,d1
  1394. cmp.w #%0000110011111100,d1
  1395. beq CAS2
  1396. jmp NoSuchInstruction(pc)
  1397. ;ENDFOLD
  1398. ;FOLD MovePea
  1399. ;*****************************************************************
  1400. ;** Emulation code for MOVEP **
  1401. ;** The instruction is in d0 **
  1402. ;*****************************************************************
  1403. MOVEPea:
  1404. MOVEM.L d2/a2-a3,-(sp)
  1405. move.l d0,d2
  1406. and.w #%111,d0
  1407. lsl.w #2,d0
  1408. move.l exc_a0(a5,d0.w),a2 ;get the EA
  1409. bsr ReadProgramWord ;read the displacement
  1410. ext.l d0
  1411. move.l d2,d1
  1412. add.l d0,a2 ;this gives the effective address
  1413. lsr.w #9-2,d1 ;get the data register
  1414. and.w #%11100,d1
  1415. lea exc_d0(a5,d1.w),a3 ;get the data register
  1416. btst #7,d2 ;a write operation?
  1417. bne.s .writetoramP
  1418. btst #6,d2
  1419. beq.s .readwordP
  1420. ; here: long-word read transfer
  1421. move.l a2,a0
  1422. bsr ReadMemoryByte
  1423. move.l d0,d2
  1424. lea 2(a2),a0
  1425. bsr ReadMemoryByte
  1426. lsl.w #8,d2
  1427. or.b d0,d2
  1428. lea 4(a2),a0
  1429. bsr ReadMemoryByte
  1430. lsl.l #8,d2
  1431. or.b d0,d2
  1432. lea 6(a2),a0
  1433. bsr ReadMemoryByte
  1434. lsl.l #8,d2
  1435. or.b d0,d2
  1436. move.l d2,(a3)
  1437. bra.s .exitP
  1438. .readwordP:
  1439. move.l a2,a0
  1440. bsr ReadMemoryByte
  1441. move.l d0,d2
  1442. lea 2(a2),a0
  1443. bsr ReadMemoryByte
  1444. lsl.w #8,d2
  1445. or.b d0,d2
  1446. move.l (a3),d1
  1447. move.w d2,d1
  1448. move.l d1,(a3)
  1449. bra.s .exitP
  1450. .writetoramP:
  1451. move.l d2,d1
  1452. move.l (a3),d2
  1453. btst #6,d1
  1454. beq.s .writewordP
  1455. move.l d2,d0
  1456. move.l a2,a0
  1457. rol.l #8,d0
  1458. bsr WriteMemoryByte
  1459. move.l d2,d0
  1460. lea 2(a2),a0
  1461. swap d0
  1462. bsr WriteMemoryByte
  1463. addq.l #4,a2
  1464. .writewordP:
  1465. move.l d2,d0
  1466. move.l a2,a0
  1467. lsr.w #8,d0
  1468. bsr WriteMemoryByte
  1469. move.l d2,d0
  1470. lea 2(a2),a0
  1471. bsr WriteMemoryByte
  1472. .exitP:
  1473. MOVEM.L (sp)+,d2/a2-a3
  1474. rts
  1475. ;ENDFOLD
  1476. ;FOLD Cmp2ea
  1477. ;*****************************************************************
  1478. ;** Emulation code for the cmp2 and chk2 instruction **
  1479. ;** The instruction is in d0 **
  1480. ;*****************************************************************
  1481. CMP2ea:
  1482. MOVEM.L d2-d5/a2-a3,-(sp)
  1483. move.l d0,d1 ;keep ea
  1484. moveq #1,d3 ;will be size
  1485. move.l d0,d2
  1486. rol.w #7,d1 ;place bits
  1487. and.b #%11,d1 ;of the size into d0
  1488. lsl.b d1,d3 ;size is now in d3 (1,2,4)
  1489. bsr ReadProgramWord ;read the extension word
  1490. move.w d0,d5
  1491. and.w #%0000111111111111,d0
  1492. bne .illegalC
  1493. ; note that pre/post is forbidden here.
  1494. moveq #0,d1
  1495. move.l d2,d0 ;restore EA
  1496. bsr GetEffectiveEA ;load EA->a0
  1497. move.w d5,d0
  1498. move.l a0,a3 ;keep me
  1499. rol.w #6,d0 ;extract register index
  1500. and.w #%111100,d0 ;only the register index
  1501. lea exc_d0(a5,d0.w),a2 ;get the register to compare against
  1502.  
  1503. move.l d3,d1
  1504. move.l a3,a0
  1505. bsr ReadMemory ;read the upper bound
  1506. move.l d3,d1
  1507. move.l d0,d2 ;put the upper bound here
  1508. lea (a3,d1.w),a0
  1509. bsr ReadMemory ;read the lower bound
  1510. move.l d3,d1
  1511. subq.l #1,d1 ;keep size-1
  1512. move.l d0,d3 ;put it here.
  1513. lsl.w #2,d1 ;two instructions per extension
  1514. jmp .extendC(pc,d1.w) ;sign-extend (always, even when comparing data)
  1515. .extendC:
  1516. ext.w d2 ;for byte-access
  1517. ext.w d3
  1518. ext.l d2 ;for word access
  1519. ext.l d3
  1520. nop
  1521. nop ;skipped over for longwords
  1522. moveq #0,d4 ;condition codes
  1523. move.l (a2),d0 ;get the value to compare
  1524. btst #15,d5 ;do we compare address registers?
  1525. bne.s .compareaddressC
  1526. ; here we also need to extend the data register
  1527. lsr.w #1,d1
  1528. jmp .extend2(pc,d1.w)
  1529. .extend2:
  1530. ext.w d0 ;for byte
  1531. ext.l d0 ;for word
  1532. nop ;skipped over
  1533. .compareaddressC:
  1534. sub.l d3,d0 ;register - lower
  1535. bne.s .notzeroC
  1536. bset #2,d4 ;set Z bit
  1537. .notzeroC:
  1538. sub.l d3,d2 ;upper-lower: maximum bound
  1539. cmp.l d0,d2 ;register > bounds?
  1540. bne.s .notzero2
  1541. bset #2,d4 ;set Z here as well
  1542. .notzero2:
  1543. bcc.s .inboundsC
  1544. bset #0,d4 ;keep bounds
  1545.  
  1546. .inboundsC:
  1547. move.b 1+exc_sr(a5),d0
  1548. and.b #%11010,d0 ;keep V and N alive
  1549. or.b d4,d0
  1550. move.b d0,1+exc_sr(a5)
  1551.  
  1552. btst #11,d5 ;trap or condition codes?
  1553. beq.s .iscmp2 ;do nothing here.
  1554. btst #0,d0 ;was out of bounds?
  1555. bne.s .createtrapC
  1556. .iscmp2:
  1557. MOVEM.L (sp)+,d2-d5/a2-a3
  1558. rts
  1559. .illegalC:
  1560. jmp NoSuchInstruction(pc)
  1561. .createtrapC:
  1562. jmp GenerateChkException(pc)
  1563. ;ENDFOLD
  1564. ;FOLD CAS2
  1565. ;*****************************************************************
  1566. ;** Emulation code for CAS2 **
  1567. ;** Actually, this really should not be used, but if a MacOs **
  1568. ;** is running natively on this machine, it nevertheless might **
  1569. ;** The instruction is in d0 **
  1570. ;*****************************************************************
  1571. CAS2:
  1572. MOVEM.L d2-d6/a2-a3,-(sp)
  1573. move.l d0,d6 ;keep the instruction, bit 9 is the size flag (0=word,1=long)
  1574. bsr ReadProgramWord ;extract first extension word
  1575. move.l d0,d1
  1576. and.w #%0000111000111000,d1
  1577. bne .illegalCAS ;unused bits must be zero
  1578. move.l d0,d1
  1579. move.l d0,d2
  1580. move.l d0,d3
  1581. rol.w #4+2,d1 ;access memory register
  1582. ror.w #6-2,d2
  1583. rol.w #2,d3
  1584. and.w #%111100,d1
  1585. and.w #%011100,d2
  1586. and.w #%011100,d3
  1587. move.l exc_d0(a5,d1.w),a2 ;get first memory register
  1588. move.l exc_d0(a5,d2.w),d2 ;get first update value
  1589. pea exc_d0(a5,d3.w) ;address of first compare operand
  1590. move.l exc_d0(a5,d3.w),d3 ;get first compare value
  1591.  
  1592. bsr ReadProgramWord ;get the second extension word
  1593. move.l d0,d1
  1594. and.w #%0000111000111000,d1
  1595. bne .illegalCAS ;unused bits must be zero
  1596. move.l d0,d1
  1597. move.l d0,d4
  1598. move.l d0,d5
  1599. rol.w #4+2,d1 ;access memory register
  1600. ror.w #6-2,d4
  1601. rol.w #2,d5
  1602. and.w #%111100,d1
  1603. and.w #%011100,d4
  1604. and.w #%011100,d5
  1605. move.l exc_d0(a5,d1.w),a3 ;get second memory register
  1606. move.l exc_d0(a5,d4.w),d4 ;get second update value
  1607. pea exc_d0(a5,d5.w) ;address of second compare operand
  1608. move.l exc_d0(a5,d5.w),d5 ;get second compare value
  1609.  
  1610. ; now comes the tricky part
  1611. ; the phoenix core does not have any way to lock the bus
  1612. ; hence block interrupts and hope the best that we
  1613. ; are the only CPU on the bus
  1614. ; Unfortunately, due to the way how the cas comparison is
  1615. ; defined, the memory operand is the second (destination)
  1616. ; operand of the compare. Yuck!
  1617. ;
  1618. ; Note: In case the core should ever get a MMU, the functions
  1619. ; below require updating for checking the validity of the
  1620. ; pages and generate a bus error accordingly.
  1621.  
  1622. ori.w #$0700,sr
  1623.  
  1624. btst #9,d6
  1625. beq.s .wordsizeCAS
  1626. ; here a long-sized CAS
  1627. moveq #4,d1
  1628. move.l a2,a0
  1629. bsr CheckPage
  1630. moveq #4,d1
  1631. move.l a3,a0
  1632. bsr CheckPage
  1633.  
  1634. ; get memory
  1635. move.l (a2),d0
  1636. move.l (a3),d1
  1637. cmp.l d3,d0 ;first comparison
  1638. move.w sr,d6 ;store result of comparison
  1639. bne.s .noupdatelCAS
  1640. cmp.l d5,d1 ;second comparison
  1641. move.w sr,d6 ;store result of comparison
  1642. bne.s .noupdatelCAS
  1643. ; here: word sized update
  1644. move.l d2,(a2) ;update first operand
  1645. move.l d4,(a3) ;update second operand
  1646. bra.s .casdoneCAS
  1647. .noupdatelCAS:
  1648. move.l (a2),d3 ;otherwise, update the compare operands
  1649. move.l (a3),d5
  1650. bra.s .casdoneCAS
  1651. ; and now the word-sized CAS
  1652. .wordsizeCAS:
  1653. moveq #2,d1
  1654. move.l a2,a0
  1655. bsr CheckPage
  1656. moveq #2,d1
  1657. move.l a3,a0
  1658. bsr CheckPage
  1659.  
  1660. ; get memory
  1661. move.w (a2),d0
  1662. move.w (a3),d1
  1663. cmp.w d3,d0 ;first comparison
  1664. move.w sr,d6 ;store result of comparison
  1665. bne.s .noupdatewCAS
  1666. cmp.w d5,d1 ;second comparison
  1667. move.w sr,d6 ;store result of comparison
  1668. bne.s .noupdatewCAS
  1669. ; here: word sized update
  1670. move.w d2,(a2) ;update first operand
  1671. move.w d4,(a3) ;update second operand
  1672. bra.s .casdoneCAS
  1673. .noupdatewCAS:
  1674. move.w (a2),d3 ;otherwise, update the compare operands
  1675. move.w (a3),d5
  1676. ; cas done here.
  1677. .casdoneCAS:
  1678. move.w exc_sr(a5),d0 ;restore the interrupt level
  1679. move.w d6,d1
  1680. move.w d0,d2
  1681. and.w #%0000011100000000,d0 ;get the IRQ level
  1682. and.w #%1111100011111111,d1
  1683. or.w d1,d0
  1684. move.w d0,sr ;re-enable IRQs
  1685.  
  1686. and.b #%01111,d6 ;mask out the result of the compare
  1687. and.b #%10000,d2 ;leave X and everything else alone
  1688. or.b d6,d2
  1689. move.b d2,1+exc_sr(a5) ;update the condition codes
  1690.  
  1691. movem.l (a7)+,a0-a1 ;get address of second and first compare operand
  1692. move.l d5,(a0) ;update second compare
  1693. move.l d3,(a1) ;update first compare
  1694.  
  1695. MOVEM.L (sp)+,d2-d6/a2-a3
  1696. rts
  1697. .illegalCAS:
  1698. jmp NoSuchInstruction(pc)
  1699. ;ENDFOLD
  1700. ;FOLD LineEVector
  1701. ;*****************************************************************
  1702. ;** Emulation code for line E instructions **
  1703. ;** The instruction is in d0 **
  1704. ;*****************************************************************
  1705. LineEVector:
  1706. move.w d0,d1
  1707. and.w #%1111111111000000,d1
  1708. cmp.w #%1110101011000000,d1
  1709. beq BFCHG
  1710. cmp.w #%1110110011000000,d1
  1711. beq BFCLR
  1712. cmp.w #%1110101111000000,d1
  1713. beq BFEXTS
  1714. cmp.w #%1110100111000000,d1
  1715. beq BFEXTU
  1716. cmp.w #%1110110111000000,d1
  1717. beq BFFFO
  1718. cmp.w #%1110111111000000,d1
  1719. beq BFINS
  1720. cmp.w #%1110111011000000,d1
  1721. beq BFSET
  1722. cmp.w #%1110100011000000,d1
  1723. beq BFTST
  1724. jmp NoSuchInstruction(pc)
  1725. ;ENDFOLD
  1726. ;FOLD BitfieldPrepareMasks
  1727. ;*****************************************************************
  1728. ;** BitfieldPrepareMasks **
  1729. ;** Prepare all masks and ea pointers for a bitfield **
  1730. ;** Input: d0: the EA **
  1731. ;** d1: set if constant EAs are acceptable, i.e. d(PC) **
  1732. ;** Output: **
  1733. ;** a2: the effective address of the first byte **
  1734. ;** a4: the effective address of the last byte **
  1735. ;** d3: the first byte mask, and the last byte mask **
  1736. ;** d5: bits in the first byte, rightshift of the last **
  1737. ;** d6: the bit number of the first bit, in normal **
  1738. ;** enumbering (i.e. 7 is the MSB) **
  1739. ;** d7: left-shift to align the first memory byte **
  1740. ;** with the MSB of the data to insert **
  1741. ;** a3: the pointer to the source/destination register **
  1742. ;** d2: offset of the MSB of the first memory byte **
  1743. ;** this may be negative! **
  1744. ;*****************************************************************
  1745. BitfieldPrepareMasks:
  1746. and.w #%111111,d0 ;extract the EA information
  1747. move.l d0,d5 ;keep it
  1748. bsr ReadProgramWord ;get the extension word
  1749. move.l d0,d3
  1750. cmp.w #%111100,d5 ;immediate is never legal
  1751. bhs .illegalBF ;and everything above is invalid anyhow
  1752. cmp.w #%111001,d5 ;Absolute always works
  1753. bls.s .nopcBF
  1754. tst.b d1 ;is d(PC) acceptable?
  1755. beq .illegalBF ;nope.
  1756. .nopcBF:
  1757. cmp.w #%000111,d5 ;a data register (yes, that is supported!)
  1758. bls.s .bitfielddataBF
  1759. ;here: is a regular EA
  1760. moveq #0,d1 ;no post/predecrement
  1761. move.l d5,d0 ;restore from above.
  1762. bsr GetEffectiveEA ;address register is filtered out
  1763. move.l a0,a2 ;keep me
  1764. bra.s .foundeaBF
  1765. .bitfielddataBF:
  1766. and.w #%000111,d5 ;bit address
  1767. lsl.w #2,d5
  1768. lea exc_d0(a5,d5.w),a2 ;address of the data register that is addressed
  1769. .foundeaBF:
  1770. ;at this point, a2 contains the base EA or address of the register,
  1771. ;d5 the <ea> mode itself and d3 te extension word.
  1772. move.w d3,d0 ;get the extension register
  1773. bmi .illegalBF ;the MSB must always be zero
  1774. rol.w #4+2,d0 ;extract the source/destination register
  1775. and.w #%11100,d0
  1776. lea exc_d0(a5,d0.w),a3 ;goes to a3
  1777. ; extract now the base offset of the bitfield
  1778. moveq #0,d2
  1779. move.w d3,d2
  1780. lsr.l #6,d2
  1781. and.w #%11111,d2 ;0..31
  1782. btst #11,d3 ;offset in a register?
  1783. beq.s .absoluteoffsBF
  1784. cmp.w #7,d2 ;only 7 data registers
  1785. bhi .illegalBF
  1786. lsl.w #2,d2
  1787. move.l exc_d0(a5,d2.w),d2 ;get the contents of the data register
  1788. .absoluteoffsBF:
  1789. ;offset is now in d2, now go for the field size
  1790. move.l d3,d4
  1791. and.w #%11111,d4 ;only 5 bits
  1792. btst #5,d3
  1793. beq.s .absolutesizeBF
  1794. cmp.w #7,d4 ;only 7 data registers
  1795. bhi.s .illegalBF
  1796. lsl.w #2,d4
  1797. move.l exc_d0(a5,d4.w),d4 ;get the contents of the data register
  1798. .absolutesizeBF:
  1799. subq.w #1,d4
  1800. and.w #%11111,d4
  1801. moveq #0,d3 ;reset for later
  1802. addq.w #1,d4 ;size is modulo 32, 0 maps to 32.
  1803. ext.l d4 ;is always positive, just erase the upper bits
  1804. ;at this point, d2 is the start bit offset of the bitfield and d4
  1805. ;is the size of the bitfield in bits, from 1 to 32.
  1806. add.l d2,d4
  1807. subq.l #1,d4 ;last bit of the bitfield
  1808. ;if the bitfield specifies a register, adjust the sizes
  1809. and.w #%111000,d5 ;register ea?
  1810. bne.s .inmemoryBF
  1811. ;clamp the range to 0..31. Unclear what happens here in reality.
  1812. ;we just take values modulo 32 and hope the best.
  1813. and.w #%11111,d2
  1814. and.w #%11111,d4
  1815. cmp.l d4,d2
  1816. blo.s .inmemoryBF
  1817. exg d2,d4 ;sort to the correct order
  1818. .inmemoryBF:
  1819. ;recompute the size of the bitfield after clamping and clipping
  1820. move.l d4,d7
  1821. sub.l d2,d7 ;is size-1
  1822. ;this is the number of the bit that must be rolled into the
  1823. ;first byte of the target bitfield
  1824.  
  1825. ;here bitfield start and end are in d2 and d4,
  1826. ;the base ea is in a2, and the source/destination register in a3
  1827. ;compute now the masks and byte offsets.
  1828. ;First go for the byte offsets.
  1829. move.l d2,d0
  1830. move.l d4,d1
  1831. asr.l #3,d0 ;note that the offsets are signed.
  1832. asr.l #3,d1
  1833. lea (a2,d1.l),a4 ;last byte
  1834. lea (a2,d0.l),a2 ;first byte
  1835. ;compute now the first byte mask and the last byte mask
  1836. move.w #$00ff,d3 ;first byte mask
  1837. moveq #0,d5 ;clear already d5 for the next steps
  1838. moveq #0,d0 ;clear upper bits of d0 for the next steps
  1839. move.l d3,d1
  1840. move.b d2,d5
  1841. move.b d4,d0
  1842. not.b d0 ;maps 0->7,1->6...7->0
  1843. and.b #7,d5
  1844. and.b #7,d0
  1845. lsr.b d5,d3
  1846. lsl.b d0,d1
  1847. swap d1
  1848. or.l d1,d3 ;place in the upper bits of d3
  1849. ;Register d3, first and last byte mask, are now ready.
  1850. ;compute now the bit counter, i.e. number of bits in the first
  1851. ;word. This goes into d5.
  1852. neg.b d5
  1853. addq.b #8,d5 ;this maps 0->8,1->7 etc, which is the number of bits
  1854. ;compute now the number of bits to rotate the first byte for insertion
  1855. ;this is given as the bit position of the MSB of the bits to insert, which
  1856. ;is d7, minus the target position, which is d5-1. The number of left
  1857. ;shifts is d5-1-d7 = not(d7-d5)
  1858. sub.b d5,d7
  1859. ;Compute now the downshift to move the last byte into the right place
  1860. ;for bit-extraction. This goes into the upper bits of d5. This is already in d0
  1861. swap d0
  1862. not.b d7
  1863. move.l d5,d6
  1864. and.b #%11111,d7 ;actually, not really required.
  1865. or.l d0,d5
  1866. ;Compute now the bit number of the MSB in the first byte. This is given by
  1867. ;the byte count minus-1
  1868. subq.w #1,d6
  1869. ;Compute the bit offset of the MSB of the first byte within the bitfield.
  1870. ;this is given as the bit-offset, rounded down to the previous multiple
  1871. ;of eight.
  1872. and.b #$f8,d2 ;this is the necessary round-down, also for negative
  1873. ;is now in d2
  1874. rts
  1875. .illegalBF:
  1876. jmp NoSuchInstruction(pc)
  1877. ;ENDFOLD
  1878. ;FOLD BFTST
  1879. ;*****************************************************************
  1880. ;** BFTST **
  1881. ;** Set the condition codes according to the bitfield value **
  1882. ;** d0 = the opcode **
  1883. ;** Z is set if the bitfield is completely zero, **
  1884. ;** N is set if the MSB of the bitfield is one **
  1885. ;** C is cleared, V is cleared, X is left alone **
  1886. ;*****************************************************************
  1887. BFTST:
  1888. MOVEM.L d2-d7/a2-a4,-(sp)
  1889. moveq #1,d1 ;constant EA is ok.
  1890. bsr BitfieldPrepareMasks
  1891. lea exc_d0(a5),a0
  1892. cmp.l a3,a0 ;register bits must be zero
  1893. bne.s .illegalBFTST
  1894.  
  1895. move.l a2,a0
  1896. bsr ReadMemoryByte
  1897. and.b d3,d0 ;apply the first byte mask
  1898. moveq #0,d7 ;for zero-testing
  1899. btst d6,d0 ;set the N bit?
  1900. beq.s .nonegBFTST
  1901. bset #31,d7 ;keep the result for the N-test
  1902. .nonegBFTST:
  1903. swap d3
  1904. ;??? do
  1905. cmp.l a4,a2 ;reached the last word?
  1906. ;??? break.s hs
  1907. or.b d0,d7 ;include in the zero mask
  1908. addq.l #1,a2
  1909. move.l a2,a0
  1910. bsr ReadMemoryByte
  1911. ;??? loop.s
  1912. ;last byte is now in d0
  1913. and.b d3,d0 ;include the last-byte mask
  1914. or.b d0,d7 ;include it.
  1915.  
  1916. and.b #%10000,1+exc_sr(a5) ;clear bits
  1917. tst.l d7 ;first bit set?
  1918. bpl.s .notfirstBFTST
  1919. bset #3,1+exc_sr(a5) ;set N bit
  1920. .notfirstBFTST:
  1921. tst.b d7 ;completely zero?
  1922. bne.s .notzeroBFTST
  1923. bset #2,1+exc_sr(a5) ;set Z bit
  1924. .notzeroBFTST:
  1925. MOVEM.L (sp)+,d2-d7/a2-a4
  1926. rts
  1927. .illegalBFTST:
  1928. jmp NoSuchInstruction(pc)
  1929. ;ENDFOLD
  1930. ;FOLD BFSET
  1931. ;*****************************************************************
  1932. ;** BFSET **
  1933. ;** Set the condition codes according to the bitfield value **
  1934. ;** then set all bits in the bitfield **
  1935. ;** d0 = the opcode **
  1936. ;** Z is set if the bitfield is completely zero, **
  1937. ;** N is set if the MSB of the bitfield is one **
  1938. ;** C is cleared, V is cleared, X is left alone **
  1939. ;*****************************************************************
  1940. BFSET:
  1941. MOVEM.L d2-d7/a2-a4,-(sp)
  1942. moveq #0,d1 ;constant EA is not ok.
  1943. bsr BitfieldPrepareMasks
  1944. lea exc_d0(a5),a0
  1945. cmp.l a3,a0 ;register bits must be zero
  1946. bne.s .illegalBFSET
  1947.  
  1948. move.l a2,a0
  1949. bsr ReadMemoryByte
  1950. move.b d0,d1 ;keep the bits
  1951. moveq #0,d7 ;for zero-testing
  1952. and.b d3,d0 ;apply the first byte mask
  1953. btst d6,d0 ;set the N bit?
  1954. beq.s .nonegBFSET
  1955. bset #31,d7 ;keep the result for the N-test
  1956. .nonegBFSET:
  1957. ;??? do
  1958. cmp.l a4,a2 ;reached the last word?
  1959. ;??? break.s hs
  1960. or.b d0,d7 ;include in the zero mask
  1961. or.b d3,d1 ;include the mask
  1962. move.l a2,a0
  1963. move.b d1,d0
  1964. bsr WriteMemoryByte ;write the masked value back
  1965. addq.l #1,a2
  1966. move.l a2,a0
  1967. bsr ReadMemoryByte
  1968. move.b d0,d1 ;keep data
  1969. st.b d3 ;completely inside, set all bits
  1970. ;??? loop.s
  1971. ;last byte is now in d0, current mask in d3
  1972. move.b d3,d2 ;get current mask->d2
  1973. swap d3 ;last byte mask
  1974. and.b d3,d0 ;include the last-byte mask
  1975. and.b d3,d2 ;joint mask
  1976. or.b d0,d7 ;include it.
  1977. or.b d2,d1
  1978. move.l a2,a0
  1979. move.b d1,d0
  1980. bsr WriteMemoryByte
  1981.  
  1982. and.b #%10000,1+exc_sr(a5) ;clear bits
  1983. tst.l d7 ;first bit set?
  1984. bpl.s .notfirstBFSET
  1985. bset #3,1+exc_sr(a5) ;set N bit
  1986. .notfirstBFSET:
  1987. tst.b d7 ;completely zero?
  1988. bne.s .notzeroBFSET
  1989. bset #2,1+exc_sr(a5) ;set Z bit
  1990. .notzeroBFSET:
  1991. MOVEM.L (sp)+,d2-d7/a2-a4
  1992. rts
  1993. .illegalBFSET:
  1994. jmp NoSuchInstruction(pc)
  1995. ;ENDFOLD
  1996. ;FOLD BFCLR
  1997. ;*****************************************************************
  1998. ;** BFCLR **
  1999. ;** Set the condition codes according to the bitfield value **
  2000. ;** then clear all bits in the bitfield **
  2001. ;** d0 = the opcode **
  2002. ;** Z is set if the bitfield is completely zero, **
  2003. ;** N is set if the MSB of the bitfield is one **
  2004. ;** C is cleared, V is cleared, X is left alone **
  2005. ;*****************************************************************
  2006. BFCLR:
  2007. MOVEM.L d2-d7/a2-a4,-(sp)
  2008. moveq #0,d1 ;constant EA is not ok.
  2009. bsr BitfieldPrepareMasks
  2010. lea exc_d0(a5),a0
  2011. cmp.l a3,a0 ;register bits must be zero
  2012. bne.s .illegalBFCLR
  2013.  
  2014. move.l a2,a0
  2015. bsr ReadMemoryByte
  2016. move.b d0,d1 ;keep the bits
  2017. moveq #0,d7 ;for zero-testing
  2018. and.b d3,d0 ;apply the first byte mask
  2019. btst d6,d0 ;set the N bit?
  2020. beq.s .nonegBFCLR
  2021. bset #31,d7 ;keep the result for the N-test
  2022. .nonegBFCLR:
  2023. ;??? do
  2024. cmp.l a4,a2 ;reached the last word?
  2025. ;??? break.s hs
  2026. or.b d0,d7 ;include in the zero mask
  2027. not.b d1
  2028. or.b d3,d1 ;clear all non-masked bits
  2029. not.b d1
  2030. move.l a2,a0
  2031. move.b d1,d0
  2032. bsr WriteMemoryByte ;write the masked value back
  2033. addq.l #1,a2
  2034. move.l a2,a0
  2035. bsr ReadMemoryByte
  2036. move.b d0,d1
  2037. st.b d3 ;completely inside, clear all bits
  2038. ;??? loop.s
  2039. ;last byte is now in d0
  2040. move.b d3,d2
  2041. swap d3
  2042. and.b d3,d0 ;include the last-byte mask
  2043. and.b d3,d2 ;joint mask
  2044. not.b d1
  2045. or.b d0,d7 ;include it.
  2046. or.b d2,d1
  2047. not.b d1
  2048. move.l a2,a0
  2049. move.b d1,d0
  2050. bsr WriteMemoryByte
  2051.  
  2052. and.b #%10000,1+exc_sr(a5) ;clear bits
  2053. tst.l d7 ;first bit set?
  2054. bpl.s .notfirstBFCLR
  2055. bset #3,1+exc_sr(a5) ;set N bit
  2056. .notfirstBFCLR:
  2057. tst.b d7 ;completely zero?
  2058. bne.s .notzeroBFCLR
  2059. bset #2,1+exc_sr(a5) ;set Z bit
  2060. .notzeroBFCLR:
  2061. MOVEM.L (sp)+,d2-d7/a2-a4
  2062. rts
  2063. .illegalBFCLR:
  2064. jmp NoSuchInstruction(pc)
  2065. ;ENDFOLD
  2066. ;FOLD BFCHG
  2067. ;*****************************************************************
  2068. ;** BFCHG **
  2069. ;** Set the condition codes according to the bitfield value **
  2070. ;** then complement all bits in the bitfield **
  2071. ;** d0 = the opcode **
  2072. ;** Z is set if the bitfield is completely zero, **
  2073. ;** N is set if the MSB of the bitfield is one **
  2074. ;** C is cleared, V is cleared, X is left alone **
  2075. ;*****************************************************************
  2076. BFCHG:
  2077. MOVEM.L d2-d7/a2-a4,-(sp)
  2078. moveq #0,d1 ;constant EA is not ok.
  2079. bsr BitfieldPrepareMasks
  2080. lea exc_d0(a5),a0
  2081. cmp.l a3,a0 ;register bits must be zero
  2082. bne.s .illegalBFCHG
  2083.  
  2084. move.l a2,a0
  2085. bsr ReadMemoryByte
  2086. move.b d0,d1 ;keep the bits
  2087. moveq #0,d7 ;for zero-testing
  2088. and.b d3,d0 ;apply the first byte mask
  2089. btst d6,d0 ;set the N bit?
  2090. beq.s .nonegBFCHG
  2091. bset #31,d7 ;keep the result for the N-test
  2092. .nonegBFCHG:
  2093. ;??? do
  2094. cmp.l a4,a2 ;reached the last word?
  2095. ;??? break.s hs
  2096. or.b d0,d7 ;include in the zero mask
  2097. eor.b d3,d1 ;complement all non-masked bits
  2098. move.l a2,a0
  2099. move.b d1,d0
  2100. bsr WriteMemoryByte ;write the masked value back
  2101. addq.l #1,a2
  2102. move.l a2,a0
  2103. bsr ReadMemoryByte
  2104. move.b d0,d1
  2105. st.b d3 ;completely inside, complement all bits
  2106. ;??? loop.s
  2107. ;last byte is now in d0
  2108. move.b d3,d2 ;current mask
  2109. swap d3
  2110. and.b d3,d0 ;include the last-byte mask
  2111. and.b d3,d2 ;joint mask
  2112. or.b d0,d7 ;include it.
  2113. eor.b d2,d1
  2114. move.l a2,a0
  2115. move.b d1,d0
  2116. bsr WriteMemoryByte
  2117.  
  2118. and.b #%10000,1+exc_sr(a5) ;clear bits
  2119. tst.l d7 ;first bit set?
  2120. bpl.s .notfirstBFCHG
  2121. bset #3,1+exc_sr(a5) ;set N bit
  2122. .notfirstBFCHG:
  2123. tst.b d7 ;completely zero?
  2124. bne.s .notzeroBFCHG
  2125. bset #2,1+exc_sr(a5) ;set Z bit
  2126. .notzeroBFCHG:
  2127. MOVEM.L (sp)+,d2-d7/a2-a4
  2128. rts
  2129. .illegalBFCHG:
  2130. jmp NoSuchInstruction(pc)
  2131. ;ENDFOLD
  2132. ;FOLD BFEXTU
  2133. ;*****************************************************************
  2134. ;** BFEXTU **
  2135. ;** Set the condition codes according to the bitfield value **
  2136. ;** extract the bitfield to the target register **
  2137. ;** d0 = the opcode **
  2138. ;** Z is set if the bitfield is completely zero, **
  2139. ;** N is set if the MSB of the bitfield is one **
  2140. ;** C is cleared, V is cleared, X is left alone **
  2141. ;*****************************************************************
  2142. BFEXTU:
  2143. MOVEM.L d2-d7/a2-a4,-(sp)
  2144. moveq #1,d1 ;constant EA is ok.
  2145. bsr BitfieldPrepareMasks
  2146.  
  2147. move.l a2,a0
  2148. bsr ReadMemoryByte
  2149. and.b d3,d0 ;apply the first byte mask
  2150. moveq #0,d7 ;for zero-testing
  2151. btst d6,d0 ;set the N bit?
  2152. beq.s .nonegBFEXT
  2153. bset #31,d7 ;keep the result for the N-test
  2154. .nonegBFEXT:
  2155. swap d3
  2156. moveq #0,d6 ;output data
  2157. ;??? do
  2158. cmp.l a4,a2 ;reached the last word?
  2159. ;??? break.s hs
  2160. or.b d0,d7 ;include in the zero mask
  2161. lsl.l d5,d6 ;make room in the register
  2162. addq.l #1,a2
  2163. or.b d0,d6 ;include the new bits
  2164. move.l a2,a0
  2165. bsr ReadMemoryByte
  2166. move.b #8,d5 ;next set is 8 bits long
  2167. ;??? loop.s
  2168. ;last byte is now in d0
  2169. and.b d3,d0 ;include the last-byte mask
  2170. rol.l d5,d6 ;make room in the output register
  2171. ;there is a specific corner case here if the output is large
  2172. ;enough, so use the spare bits in the lower end to roll the
  2173. ;MSBs in
  2174. or.b d0,d7 ;include it.
  2175. not.b d6 ;mask out the bits we want to set
  2176. swap d5 ;get downshift for last byte
  2177. or.b d3,d6
  2178. not.b d6
  2179. or.b d0,d6 ;include the new bits
  2180. ror.l d5,d6 ;rotate back into the target position
  2181.  
  2182. and.b #%10000,1+exc_sr(a5) ;clear bits
  2183. move.l d6,(a3) ;place in target register.
  2184.  
  2185. tst.l d7 ;first bit set?
  2186. bpl.s .notfirstBFEXT
  2187. bset #3,1+exc_sr(a5) ;set N bit
  2188. .notfirstBFEXT:
  2189. tst.b d7 ;completely zero?
  2190. bne.s .notzeroBFEXT
  2191. bset #2,1+exc_sr(a5) ;set Z bit
  2192. .notzeroBFEXT:
  2193. MOVEM.L (sp)+,d2-d7/a2-a4
  2194. rts
  2195. ;ENDFOLD
  2196. ;FOLD BFEXTS
  2197. ;*****************************************************************
  2198. ;** BFEXTS **
  2199. ;** Set the condition codes according to the bitfield value **
  2200. ;** extract the bitfield to the target register, sign extended **
  2201. ;** d0 = the opcode **
  2202. ;** Z is set if the bitfield is completely zero, **
  2203. ;** N is set if the MSB of the bitfield is one **
  2204. ;** C is cleared, V is cleared, X is left alone **
  2205. ;*****************************************************************
  2206. BFEXTS:
  2207. MOVEM.L d2-d7/a2-a4,-(sp)
  2208. moveq #1,d1 ;constant EA is ok.
  2209. bsr BitfieldPrepareMasks
  2210.  
  2211. move.l a2,a0
  2212. bsr ReadMemoryByte
  2213. and.b d3,d0 ;apply the first byte mask
  2214. moveq #0,d1
  2215. moveq #0,d7 ;for zero-testing
  2216. btst d6,d0 ;set the N bit?
  2217. beq.s .nonegBFEXTS
  2218. bset #31,d7 ;keep the result for the N-test
  2219. moveq #-1,d1 ;roll in one-bits, not zero bits
  2220. .nonegBFEXTS:
  2221. move.l d1,d6 ;output data
  2222. ;??? do
  2223. cmp.l a4,a2 ;reached the last word?
  2224. ;??? break.s hs
  2225. or.b d0,d7 ;include in the zero mask
  2226. lsl.l d5,d6 ;make room in the register
  2227. addq.l #1,a2
  2228. or.b d0,d6 ;include the new bits
  2229. move.l a2,a0
  2230. bsr ReadMemoryByte
  2231. move.b #8,d5 ;next set is 8 bits long
  2232. st.b d3 ;first word mask is now all bits
  2233. ;??? loop.s
  2234. ;last byte is now in d0
  2235. move.b d3,d2 ;keep the currently active mask
  2236. swap d3
  2237. and.b d3,d0 ;include the last-byte mask
  2238. rol.l d5,d6 ;make room in the output register
  2239. ;there is a specific corner case here if the output is large
  2240. ;enough, so use the spare bits in the lower end to roll the
  2241. ;MSBs in
  2242. or.b d0,d7 ;include it.
  2243. and.b d3,d2 ;joint first and last mask
  2244. not.b d6 ;mask out the bits we want to set
  2245. swap d5 ;get downshift for last byte
  2246. or.b d2,d6
  2247. not.b d6
  2248. or.b d0,d6 ;include the new bits
  2249. ror.l d5,d6 ;rotate back into the target position
  2250.  
  2251. and.b #%10000,1+exc_sr(a5) ;clear bits
  2252. move.l d6,(a3) ;place in target register.
  2253.  
  2254. tst.l d7 ;first bit set?
  2255. bpl.s .notfirstBFEXTS
  2256. bset #3,1+exc_sr(a5) ;set N bit
  2257. .notfirstBFEXTS:
  2258. tst.b d7 ;completely zero?
  2259. bne.s .notzeroBFEXTS
  2260. bset #2,1+exc_sr(a5) ;set Z bit
  2261. .notzeroBFEXTS:
  2262. MOVEM.L (sp)+,d2-d7/a2-a4
  2263. rts
  2264. ;ENDFOLD
  2265. ;FOLD BFINS
  2266. ;*****************************************************************
  2267. ;** BFINS **
  2268. ;** Set the condition codes according to the bitfield value **
  2269. ;** Insert the target register into the bitfield **
  2270. ;** d0 = the opcode **
  2271. ;** Z is set if the bitfield is completely zero, **
  2272. ;** N is set if the MSB of the bitfield is one **
  2273. ;** C is cleared, V is cleared, X is left alone **
  2274. ;*****************************************************************
  2275. BFINS:
  2276. MOVEM.L d2-d7/a2-a4,-(sp)
  2277. moveq #0,d1 ;constant EA is notok.
  2278. bsr BitfieldPrepareMasks
  2279.  
  2280. move.l a2,a0
  2281. bsr ReadMemoryByte
  2282. move.b d0,d1 ;keep the unaltered data
  2283. move.l d7,d4 ;keep shift value
  2284. and.b d3,d0 ;apply the first byte mask
  2285. moveq #0,d2 ;the insertion mask: all clear bits affect the target memory
  2286. moveq #0,d7 ;for zero-testing
  2287. not.b d3
  2288. or.b d3,d2 ;set all bits not belonging to the data to insert
  2289. btst d6,d0 ;set the N bit?
  2290. beq.s .nonegBFINS
  2291. bset #31,d7 ;keep the result for the N-test
  2292. .nonegBFINS:
  2293. move.l (a3),d6 ;get data byte
  2294. swap d3
  2295. rol.l d4,d6 ;move in place
  2296. ;??? do
  2297. cmp.l a4,a2 ;reached the last word?
  2298. ;??? break.s hs
  2299. or.b d0,d7 ;include in the zero mask
  2300. eor.b d6,d1
  2301. and.b d2,d1 ;reset all bits to be inserted
  2302. eor.b d6,d1 ;place the data to be inserted there, keep the rest alone
  2303. move.l a2,a0
  2304. rol.l #8,d6 ;move to the next bit-pattern of the source
  2305. move.b d1,d0
  2306. bsr WriteMemoryByte ;write out the result
  2307. addq.l #1,a2
  2308. move.l a2,a0
  2309. bsr ReadMemoryByte
  2310. clr.b d2 ;all bits matter
  2311. move.b d0,d1
  2312. ;??? loop.s
  2313. ;last byte is now in d0
  2314. and.b d3,d0 ;include the last-byte mask
  2315. not.b d3
  2316. or.b d0,d7 ;include it.
  2317. or.b d3,d2 ;also in the data mask
  2318. eor.b d6,d1
  2319. and.b d2,d1
  2320. eor.b d6,d1
  2321. move.l a2,a0
  2322. move.b d1,d0
  2323. bsr WriteMemoryByte
  2324.  
  2325. and.b #%10000,1+exc_sr(a5) ;clear bits
  2326. tst.l d7 ;first bit set?
  2327. bpl.s .notfirstBFINS
  2328. bset #3,1+exc_sr(a5) ;set N bit
  2329. .notfirstBFINS:
  2330. tst.b d7 ;completely zero?
  2331. bne.s .notzeroBFINS
  2332. bset #2,1+exc_sr(a5) ;set Z bit
  2333. .notzeroBFINS:
  2334. MOVEM.L (sp)+,d2-d7/a2-a4
  2335. rts
  2336. ;ENDFOLD
  2337. ;FOLD BFFFO
  2338. ;*****************************************************************
  2339. ;** BFFFO **
  2340. ;** Set the condition codes according to the bitfield value **
  2341. ;** find the offset of the first one-bit **
  2342. ;** d0 = the opcode **
  2343. ;** Z is set if the bitfield is completely zero, **
  2344. ;** N is set if the MSB of the bitfield is one **
  2345. ;** C is cleared, V is cleared, X is left alone **
  2346. ;*****************************************************************
  2347. BFFFO:
  2348. MOVEM.L d2-d7/a2-a4/a6,-(sp)
  2349. moveq #1,d1 ;constant EA is ok.
  2350. bsr BitfieldPrepareMasks
  2351.  
  2352. move.l a2,a0
  2353. bsr ReadMemoryByte
  2354. and.w d3,d0 ;apply the first byte mask
  2355. moveq #0,d7 ;for zero-testing
  2356. btst d6,d0 ;set the N bit?
  2357. beq.s .nonegBFFFO
  2358. bset #31,d7 ;keep the result for the N-test
  2359. .nonegBFFFO:
  2360. lea FirstSetBit,a6
  2361. swap d3
  2362. ;??? do
  2363. cmp.l a4,a2 ;reached the last word?
  2364. ;??? break.s hs
  2365. or.b d0,d7 ;include in the zero mask
  2366. tst.l d6 ;already found the one-bit?
  2367. bmi.s .nobitBFFFO ;if so, only continue for zero-testing and continue reading data for consistency
  2368. moveq #0,d1
  2369. move.b (a6,d0.w),d1 ;find the first set bit in the byte, counting from left
  2370. bmi.s .nobitBFFFO ;if none set, continue
  2371. add.l d1,d2 ;add to the bit offset
  2372. moveq #-1,d6 ;is now found
  2373. .nobitBFFFO:
  2374. addq.l #1,a2
  2375. move.l a2,a0
  2376. bsr ReadMemoryByte
  2377. addq.l #8,d2 ;update the bit offset
  2378. ;??? loop.s
  2379. ;last byte is now in d0
  2380. and.w d3,d0 ;include the last-byte mask
  2381. or.b d0,d7 ;include it.
  2382. tst.l d6
  2383. bmi.s .nobit2BFFFO
  2384. moveq #0,d1
  2385. move.b d3,d1
  2386. lsr.b #1,d1
  2387. not.b d3
  2388. and.b d3,d1 ;fiddle a one-bit behind the actual bit mask
  2389. or.b d1,d0 ;if this is bit-aligned, the result would be zero, still.
  2390. move.b (a6,d0.w),d1 ;is 0...7, or $88 if zero
  2391. and.b #$0f,d1 ;only the bit number
  2392. add.l d1,d2 ;now the bit number.
  2393. .nobit2BFFFO:
  2394. and.b #%10000,1+exc_sr(a5) ;clear bits
  2395. move.l d2,(a3) ;save the result
  2396. tst.l d7 ;first bit set?
  2397. bpl.s .notfirstBFFFO
  2398. bset #3,1+exc_sr(a5) ;set N bit
  2399. .notfirstBFFFO:
  2400. tst.b d7 ;completely zero?
  2401. bne.s .notzeroBFFFO
  2402. bset #2,1+exc_sr(a5) ;set Z bit
  2403. .notzeroBFFFO:
  2404. MOVEM.L (sp)+,d2-d7/a2-a4/a6
  2405. rts
  2406. ;ENDFOLD
  2407.  
  2408.  
  2409. ; section resident_data,data
  2410.  
  2411. ;FOLD LineVectors
  2412. ;; This table defines for each line an entry point for handling
  2413. ;; the corresponding line of instructions. There are 16 lines in total.
  2414. LineVectors:
  2415. dc.l Line0Vector
  2416. dc.l NoSuchInstruction
  2417. dc.l NoSuchInstruction
  2418. dc.l NoSuchInstruction
  2419.  
  2420. dc.l Line4Vector
  2421. dc.l NoSuchInstruction
  2422. dc.l NoSuchInstruction
  2423. dc.l NoSuchInstruction
  2424.  
  2425. dc.l Line8Vector
  2426. dc.l NoSuchInstruction
  2427. dc.l NoSuchInstruction
  2428. dc.l NoSuchInstruction
  2429.  
  2430. dc.l LineCVector
  2431. dc.l NoSuchInstruction
  2432. dc.l LineEVector
  2433. dc.l NoSuchInstruction
  2434. ;ENDFOLD
  2435. ;FOLD EADecode
  2436. ;; These are the decoder functions for effective addresses
  2437. EADecode:
  2438. dc.l DecodeDx
  2439. dc.l DecodeAx
  2440. dc.l DecodeIndirect
  2441. dc.l DecodePostIncrement
  2442.  
  2443. dc.l DecodePredecrement
  2444. dc.l DecodeDisplacement
  2445. dc.l DecodeIndexed
  2446. dc.l DecodeMisc
  2447. EAMiscDecode:
  2448. dc.l AbsoluteWord
  2449. dc.l AbsoluteLong
  2450. dc.l PCDisplacement
  2451. dc.l PCIndexed
  2452.  
  2453. dc.l Immediate
  2454. dc.l Illegal
  2455. dc.l Illegal
  2456. dc.l Illegal
  2457. ;ENDFOLD
  2458. ;FOLD FirstSetBit
  2459. ; This table includes, for each byte value, the bit index of the first set bit
  2460. ; or negative if no bit is set
  2461. FirstSetBit:
  2462. dc.b $88,7,6,6,5,5,5,5,4,4,4,4,4,4,4,4
  2463. dc.b 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
  2464. dc.b 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
  2465. dc.b 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
  2466. dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  2467. dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  2468. dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  2469. dc.b 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  2470. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2471. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2472. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2473. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2474. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2475. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2476. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2477. dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  2478. ;ENDFOLD
  2479.  
  2480. ;===============================================================
  2481.  
  2482. my_RT_INIT:
  2483. moveq.l #0,d0
  2484. rts
  2485.  
  2486. my_RT_NAME:
  2487. dc.b "APOLLO-Lib",0
  2488.  
  2489. my_RT_IDSTRING:
  2490. dc.b "$VER: APOLLO-Lib 1.01 (7.6.2016) APOLLO-Team",10,0,0
  2491.  
  2492. ;===============================================================
Add Comment
Please, Sign In to add comment