2dd90b0f0c5e6119c97ee909ec5ad65c3f9eeed0
[pcsx_rearmed.git] / libpcsxcore / psxinterpreter.c
1 /***************************************************************************
2  *   Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team              *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
18  ***************************************************************************/
19
20 /*
21  * PSX assembly interpreter.
22  */
23
24 #include "psxcommon.h"
25 #include "r3000a.h"
26 #include "gte.h"
27 #include "psxhle.h"
28 #include "debug.h"
29 #include "psxinterpreter.h"
30 #include <assert.h>
31
32 static int branch = 0;
33 static int branch2 = 0;
34 static u32 branchPC;
35
36 // These macros are used to assemble the repassembler functions
37
38 #ifdef PSXCPU_LOG
39 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); 
40 #else
41 #define debugI()
42 #endif
43
44 // Subsets
45 void (*psxBSC[64])();
46 void (*psxSPC[64])();
47 void (*psxREG[32])();
48 void (*psxCP0[32])();
49 void (*psxCP2[64])(struct psxCP2Regs *regs);
50 void (*psxCP2BSC[32])();
51
52 #ifdef ICACHE_EMULATION
53 /*
54 Formula One 2001 :
55 Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
56 */
57 static u8* ICache_Addr;
58 static u8* ICache_Code;
59 uint32_t *Read_ICache(uint32_t pc)
60 {
61         uint32_t pc_bank, pc_offset, pc_cache;
62         uint8_t *IAddr, *ICode;
63
64         pc_bank = pc >> 24;
65         pc_offset = pc & 0xffffff;
66         pc_cache = pc & 0xfff;
67
68         IAddr = ICache_Addr;
69         ICode = ICache_Code;
70
71         // cached - RAM
72         if (pc_bank == 0x80 || pc_bank == 0x00)
73         {
74                 if (SWAP32(*(uint32_t *)(IAddr + pc_cache)) == pc_offset)
75                 {
76                         // Cache hit - return last opcode used
77                         return (uint32_t *)(ICode + pc_cache);
78                 }
79                 else
80                 {
81                         // Cache miss - addresses don't match
82                         // - default: 0xffffffff (not init)
83
84                         // cache line is 4 bytes wide
85                         pc_offset &= ~0xf;
86                         pc_cache &= ~0xf;
87
88                         // address line
89                         *(uint32_t *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
90                         *(uint32_t *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
91                         *(uint32_t *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
92                         *(uint32_t *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
93
94                         // opcode line
95                         pc_offset = pc & ~0xf;
96                         *(uint32_t *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
97                         *(uint32_t *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
98                         *(uint32_t *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
99                         *(uint32_t *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
100                 }
101         }
102
103         /*
104         TODO: Probably should add cached BIOS
105         */
106         // default
107         return (uint32_t *)PSXM(pc);
108 }
109 #endif
110
111 static void delayRead(int reg, u32 bpc) {
112         u32 rold, rnew;
113
114 //      SysPrintf("delayRead at %x!\n", psxRegs.pc);
115
116         rold = psxRegs.GPR.r[reg];
117         psxBSC[psxRegs.code >> 26](); // branch delay load
118         rnew = psxRegs.GPR.r[reg];
119
120         psxRegs.pc = bpc;
121
122         branch = 0;
123
124         psxRegs.GPR.r[reg] = rold;
125         execI(); // first branch opcode
126         psxRegs.GPR.r[reg] = rnew;
127
128         psxBranchTest();
129 }
130
131 static void delayWrite(int reg, u32 bpc) {
132
133 /*      SysPrintf("delayWrite at %x!\n", psxRegs.pc);
134
135         SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
136         SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
137
138         // no changes from normal behavior
139
140         psxBSC[psxRegs.code >> 26]();
141
142         branch = 0;
143         psxRegs.pc = bpc;
144
145         psxBranchTest();
146 }
147
148 static void delayReadWrite(int reg, u32 bpc) {
149
150 //      SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
151
152         // the branch delay load is skipped
153
154         branch = 0;
155         psxRegs.pc = bpc;
156
157         psxBranchTest();
158 }
159
160 // this defines shall be used with the tmp 
161 // of the next func (instead of _Funct_...)
162 #define _tFunct_  ((tmp      ) & 0x3F)  // The funct part of the instruction register 
163 #define _tRd_     ((tmp >> 11) & 0x1F)  // The rd part of the instruction register 
164 #define _tRt_     ((tmp >> 16) & 0x1F)  // The rt part of the instruction register 
165 #define _tRs_     ((tmp >> 21) & 0x1F)  // The rs part of the instruction register 
166 #define _tSa_     ((tmp >>  6) & 0x1F)  // The sa part of the instruction register
167
168 int psxTestLoadDelay(int reg, u32 tmp) {
169         if (tmp == 0) return 0; // NOP
170         switch (tmp >> 26) {
171                 case 0x00: // SPECIAL
172                         switch (_tFunct_) {
173                                 case 0x00: // SLL
174                                 case 0x02: case 0x03: // SRL/SRA
175                                         if (_tRd_ == reg && _tRt_ == reg) return 1; else
176                                         if (_tRt_ == reg) return 2; else
177                                         if (_tRd_ == reg) return 3;
178                                         break;
179
180                                 case 0x08: // JR
181                                         if (_tRs_ == reg) return 2;
182                                         break;
183                                 case 0x09: // JALR
184                                         if (_tRd_ == reg && _tRs_ == reg) return 1; else
185                                         if (_tRs_ == reg) return 2; else
186                                         if (_tRd_ == reg) return 3;
187                                         break;
188
189                                 // SYSCALL/BREAK just a break;
190
191                                 case 0x20: case 0x21: case 0x22: case 0x23:
192                                 case 0x24: case 0x25: case 0x26: case 0x27: 
193                                 case 0x2a: case 0x2b: // ADD/ADDU...
194                                 case 0x04: case 0x06: case 0x07: // SLLV...
195                                         if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
196                                         if (_tRt_ == reg || _tRs_ == reg) return 2; else
197                                         if (_tRd_ == reg) return 3;
198                                         break;
199
200                                 case 0x10: case 0x12: // MFHI/MFLO
201                                         if (_tRd_ == reg) return 3;
202                                         break;
203                                 case 0x11: case 0x13: // MTHI/MTLO
204                                         if (_tRs_ == reg) return 2;
205                                         break;
206
207                                 case 0x18: case 0x19:
208                                 case 0x1a: case 0x1b: // MULT/DIV...
209                                         if (_tRt_ == reg || _tRs_ == reg) return 2;
210                                         break;
211                         }
212                         break;
213
214                 case 0x01: // REGIMM
215                         switch (_tRt_) {
216                                 case 0x00: case 0x01:
217                                 case 0x10: case 0x11: // BLTZ/BGEZ...
218                                         // Xenogears - lbu v0 / beq v0
219                                         // - no load delay (fixes battle loading)
220                                         break;
221
222                                         if (_tRs_ == reg) return 2;
223                                         break;
224                         }
225                         break;
226
227                 // J would be just a break;
228                 case 0x03: // JAL
229                         if (31 == reg) return 3;
230                         break;
231
232                 case 0x04: case 0x05: // BEQ/BNE
233                         // Xenogears - lbu v0 / beq v0
234                         // - no load delay (fixes battle loading)
235                         break;
236
237                         if (_tRs_ == reg || _tRt_ == reg) return 2;
238                         break;
239
240                 case 0x06: case 0x07: // BLEZ/BGTZ
241                         // Xenogears - lbu v0 / beq v0
242                         // - no load delay (fixes battle loading)
243                         break;
244
245                         if (_tRs_ == reg) return 2;
246                         break;
247
248                 case 0x08: case 0x09: case 0x0a: case 0x0b:
249                 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
250                         if (_tRt_ == reg && _tRs_ == reg) return 1; else
251                         if (_tRs_ == reg) return 2; else
252                         if (_tRt_ == reg) return 3;
253                         break;
254
255                 case 0x0f: // LUI
256                         if (_tRt_ == reg) return 3;
257                         break;
258
259                 case 0x10: // COP0
260                         switch (_tFunct_) {
261                                 case 0x00: // MFC0
262                                         if (_tRt_ == reg) return 3;
263                                         break;
264                                 case 0x02: // CFC0
265                                         if (_tRt_ == reg) return 3;
266                                         break;
267                                 case 0x04: // MTC0
268                                         if (_tRt_ == reg) return 2;
269                                         break;
270                                 case 0x06: // CTC0
271                                         if (_tRt_ == reg) return 2;
272                                         break;
273                                 // RFE just a break;
274                         }
275                         break;
276
277                 case 0x12: // COP2
278                         switch (_tFunct_) {
279                                 case 0x00: 
280                                         switch (_tRs_) {
281                                                 case 0x00: // MFC2
282                                                         if (_tRt_ == reg) return 3;
283                                                         break;
284                                                 case 0x02: // CFC2
285                                                         if (_tRt_ == reg) return 3;
286                                                         break;
287                                                 case 0x04: // MTC2
288                                                         if (_tRt_ == reg) return 2;
289                                                         break;
290                                                 case 0x06: // CTC2
291                                                         if (_tRt_ == reg) return 2;
292                                                         break;
293                                         }
294                                         break;
295                                 // RTPS... break;
296                         }
297                         break;
298
299                 case 0x22: case 0x26: // LWL/LWR
300                         if (_tRt_ == reg) return 3; else
301                         if (_tRs_ == reg) return 2;
302                         break;
303
304                 case 0x20: case 0x21: case 0x23:
305                 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
306                         if (_tRt_ == reg && _tRs_ == reg) return 1; else
307                         if (_tRs_ == reg) return 2; else
308                         if (_tRt_ == reg) return 3;
309                         break;
310
311                 case 0x28: case 0x29: case 0x2a:
312                 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
313                         if (_tRt_ == reg || _tRs_ == reg) return 2;
314                         break;
315
316                 case 0x32: case 0x3a: // LWC2/SWC2
317                         if (_tRs_ == reg) return 2;
318                         break;
319         }
320
321         return 0;
322 }
323
324 void psxDelayTest(int reg, u32 bpc) {
325         u32 *code;
326         u32 tmp;
327
328         #ifdef ICACHE_EMULATION
329         if (Config.icache_emulation)
330         {
331                 code = Read_ICache(psxRegs.pc);
332         }
333         else
334         #endif
335         {
336                 code = (u32 *)PSXM(psxRegs.pc);
337         }
338
339         tmp = ((code == NULL) ? 0 : SWAP32(*code));
340         branch = 1;
341
342         switch (psxTestLoadDelay(reg, tmp)) {
343                 case 1:
344                         delayReadWrite(reg, bpc); return;
345                 case 2:
346                         delayRead(reg, bpc); return;
347                 case 3:
348                         delayWrite(reg, bpc); return;
349         }
350         psxBSC[psxRegs.code >> 26]();
351
352         branch = 0;
353         psxRegs.pc = bpc;
354
355         psxBranchTest();
356 }
357
358 static u32 psxBranchNoDelay(void) {
359         u32 *code;
360         u32 temp;
361
362         #ifdef ICACHE_EMULATION
363         if (Config.icache_emulation)
364         {
365                 code = Read_ICache(psxRegs.pc);
366         }
367         else
368         #endif
369         {
370                 code = (u32 *)PSXM(psxRegs.pc);
371         }
372         psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
373         switch (_Op_) {
374                 case 0x00: // SPECIAL
375                         switch (_Funct_) {
376                                 case 0x08: // JR
377                                         return _u32(_rRs_);
378                                 case 0x09: // JALR
379                                         temp = _u32(_rRs_);
380                                         if (_Rd_) { _SetLink(_Rd_); }
381                                         return temp;
382                         }
383                         break;
384                 case 0x01: // REGIMM
385                         switch (_Rt_) {
386                                 case 0x00: // BLTZ
387                                         if (_i32(_rRs_) < 0)
388                                                 return _BranchTarget_;
389                                         break;
390                                 case 0x01: // BGEZ
391                                         if (_i32(_rRs_) >= 0)
392                                                 return _BranchTarget_;
393                                         break;
394                                 case 0x08: // BLTZAL
395                                         if (_i32(_rRs_) < 0) {
396                                                 _SetLink(31);
397                                                 return _BranchTarget_;
398                                         }
399                                         break;
400                                 case 0x09: // BGEZAL
401                                         if (_i32(_rRs_) >= 0) {
402                                                 _SetLink(31);
403                                                 return _BranchTarget_;
404                                         }
405                                         break;
406                         }
407                         break;
408                 case 0x02: // J
409                         return _JumpTarget_;
410                 case 0x03: // JAL
411                         _SetLink(31);
412                         return _JumpTarget_;
413                 case 0x04: // BEQ
414                         if (_i32(_rRs_) == _i32(_rRt_))
415                                 return _BranchTarget_;
416                         break;
417                 case 0x05: // BNE
418                         if (_i32(_rRs_) != _i32(_rRt_))
419                                 return _BranchTarget_;
420                         break;
421                 case 0x06: // BLEZ
422                         if (_i32(_rRs_) <= 0)
423                                 return _BranchTarget_;
424                         break;
425                 case 0x07: // BGTZ
426                         if (_i32(_rRs_) > 0)
427                                 return _BranchTarget_;
428                         break;
429         }
430
431         return (u32)-1;
432 }
433
434 static int psxDelayBranchExec(u32 tar) {
435         execI();
436
437         branch = 0;
438         psxRegs.pc = tar;
439         psxRegs.cycle += BIAS;
440         psxBranchTest();
441         return 1;
442 }
443
444 static int psxDelayBranchTest(u32 tar1) {
445         u32 tar2, tmp1, tmp2;
446
447         tar2 = psxBranchNoDelay();
448         if (tar2 == (u32)-1)
449                 return 0;
450
451         debugI();
452
453         /*
454          * Branch in delay slot:
455          * - execute 1 instruction at tar1
456          * - jump to tar2 (target of branch in delay slot; this branch
457          *   has no normal delay slot, instruction at tar1 was fetched instead)
458          */
459         psxRegs.pc = tar1;
460         tmp1 = psxBranchNoDelay();
461         if (tmp1 == (u32)-1) {
462                 return psxDelayBranchExec(tar2);
463         }
464         debugI();
465         psxRegs.cycle += BIAS;
466
467         /*
468          * Got a branch at tar1:
469          * - execute 1 instruction at tar2
470          * - jump to target of that branch (tmp1)
471          */
472         psxRegs.pc = tar2;
473         tmp2 = psxBranchNoDelay();
474         if (tmp2 == (u32)-1) {
475                 return psxDelayBranchExec(tmp1);
476         }
477         debugI();
478         psxRegs.cycle += BIAS;
479
480         /*
481          * Got a branch at tar2:
482          * - execute 1 instruction at tmp1
483          * - jump to target of that branch (tmp2)
484          */
485         psxRegs.pc = tmp1;
486         return psxDelayBranchExec(tmp2);
487 }
488
489 static void doBranch(u32 tar) {
490         u32 *code;
491         u32 tmp;
492
493         branch2 = branch = 1;
494         branchPC = tar;
495
496         // check for branch in delay slot
497         if (psxDelayBranchTest(tar))
498                 return;
499
500         #ifdef ICACHE_EMULATION
501         if (Config.icache_emulation)
502         {
503                 code = Read_ICache(psxRegs.pc);
504         }
505         else
506         #endif
507         {
508                 code = (u32 *)PSXM(psxRegs.pc);
509         }
510         psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
511
512         debugI();
513
514         psxRegs.pc += 4;
515         psxRegs.cycle += BIAS;
516
517         // check for load delay
518         tmp = psxRegs.code >> 26;
519         switch (tmp) {
520                 case 0x10: // COP0
521                         switch (_Rs_) {
522                                 case 0x00: // MFC0
523                                 case 0x02: // CFC0
524                                         psxDelayTest(_Rt_, branchPC);
525                                         return;
526                         }
527                         break;
528                 case 0x12: // COP2
529                         switch (_Funct_) {
530                                 case 0x00:
531                                         switch (_Rs_) {
532                                                 case 0x00: // MFC2
533                                                 case 0x02: // CFC2
534                                                         psxDelayTest(_Rt_, branchPC);
535                                                         return;
536                                         }
537                                         break;
538                         }
539                         break;
540                 case 0x32: // LWC2
541                         psxDelayTest(_Rt_, branchPC);
542                         return;
543                 default:
544                         if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
545                                 psxDelayTest(_Rt_, branchPC);
546                                 return;
547                         }
548                         break;
549         }
550
551         psxBSC[psxRegs.code >> 26]();
552
553         branch = 0;
554         psxRegs.pc = branchPC;
555
556         psxBranchTest();
557 }
558
559 /*********************************************************
560 * Arithmetic with immediate operand                      *
561 * Format:  OP rt, rs, immediate                          *
562 *********************************************************/
563 void psxADDI()  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; }            // Rt = Rs + Im         (Exception on Integer Overflow)
564 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; }            // Rt = Rs + Im
565 void psxANDI()  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; }            // Rt = Rs And Im
566 void psxORI()   { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; }            // Rt = Rs Or  Im
567 void psxXORI()  { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; }            // Rt = Rs Xor Im
568 void psxSLTI()  { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; }            // Rt = Rs < Im         (Signed)
569 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); }              // Rt = Rs < Im         (Unsigned)
570
571 /*********************************************************
572 * Register arithmetic                                    *
573 * Format:  OP rd, rs, rt                                 *
574 *********************************************************/
575 void psxADD()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); }       // Rd = Rs + Rt         (Exception on Integer Overflow)
576 void psxADDU()  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); }       // Rd = Rs + Rt
577 void psxSUB()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); }       // Rd = Rs - Rt         (Exception on Integer Overflow)
578 void psxSUBU()  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); }       // Rd = Rs - Rt
579 void psxAND()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); }       // Rd = Rs And Rt
580 void psxOR()    { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); }       // Rd = Rs Or  Rt
581 void psxXOR()   { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); }       // Rd = Rs Xor Rt
582 void psxNOR()   { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
583 void psxSLT()   { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); }       // Rd = Rs < Rt         (Signed)
584 void psxSLTU()  { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); }       // Rd = Rs < Rt         (Unsigned)
585
586 /*********************************************************
587 * Register mult/div & Register trap logic                *
588 * Format:  OP rs, rt                                     *
589 *********************************************************/
590 void psxDIV() {
591     if (!_i32(_rRt_)) {
592         _i32(_rHi_) = _i32(_rRs_);
593         if (_i32(_rRs_) & 0x80000000) {
594             _i32(_rLo_) = 1;
595         } else {
596             _i32(_rLo_) = 0xFFFFFFFF;
597         }
598 /*
599  * Notaz said that this was "not needed" for ARM platforms and could slow it down so let's disable for ARM. 
600  * This fixes a crash issue that can happen when running Amidog's CPU test.
601  * (It still stays stuck to a black screen but at least it doesn't crash anymore)
602  */
603 #if !defined(__arm__) && !defined(__aarch64__)
604     } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
605         _i32(_rLo_) = 0x80000000;
606         _i32(_rHi_) = 0;
607 #endif
608     } else {
609         _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
610         _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
611     }
612 }
613
614 void psxDIV_stall() {
615         psxRegs.muldivBusyCycle = psxRegs.cycle + 37;
616         psxDIV();
617 }
618
619 void psxDIVU() {
620         if (_rRt_ != 0) {
621                 _rLo_ = _rRs_ / _rRt_;
622                 _rHi_ = _rRs_ % _rRt_;
623         }
624         else {
625                 _i32(_rLo_) = 0xffffffff;
626                 _i32(_rHi_) = _i32(_rRs_);
627         }
628 }
629
630 void psxDIVU_stall() {
631         psxRegs.muldivBusyCycle = psxRegs.cycle + 37;
632         psxDIVU();
633 }
634
635 void psxMULT() {
636         u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
637
638         psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
639         psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
640 }
641
642 void psxMULT_stall() {
643         // approximate, but maybe good enough
644         u32 rs = _rRs_;
645         u32 lz = __builtin_clz(((rs ^ ((s32)rs >> 21)) | 1));
646         u32 c = 7 + (2 - (lz / 11)) * 4;
647         psxRegs.muldivBusyCycle = psxRegs.cycle + c;
648         psxMULT();
649 }
650
651 void psxMULTU() {
652         u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
653
654         psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
655         psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
656 }
657
658 void psxMULTU_stall() {
659         // approximate, but maybe good enough
660         u32 lz = __builtin_clz(_rRs_ | 1);
661         u32 c = 7 + (2 - (lz / 11)) * 4;
662         psxRegs.muldivBusyCycle = psxRegs.cycle + c;
663         psxMULTU();
664 }
665
666 /*********************************************************
667 * Register branch logic                                  *
668 * Format:  OP rs, offset                                 *
669 *********************************************************/
670 #define RepZBranchi32(op)      if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
671 #define RepZBranchLinki32(op)  { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } }
672
673 void psxBGEZ()   { RepZBranchi32(>=) }      // Branch if Rs >= 0
674 void psxBGEZAL() { RepZBranchLinki32(>=) }  // Branch if Rs >= 0 and link
675 void psxBGTZ()   { RepZBranchi32(>) }       // Branch if Rs >  0
676 void psxBLEZ()   { RepZBranchi32(<=) }      // Branch if Rs <= 0
677 void psxBLTZ()   { RepZBranchi32(<) }       // Branch if Rs <  0
678 void psxBLTZAL() { RepZBranchLinki32(<) }   // Branch if Rs <  0 and link
679
680 /*********************************************************
681 * Shift arithmetic with constant shift                   *
682 * Format:  OP rd, rt, sa                                 *
683 *********************************************************/
684 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
685 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
686 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
687
688 /*********************************************************
689 * Shift arithmetic with variant register shift           *
690 * Format:  OP rd, rt, rs                                 *
691 *********************************************************/
692 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs
693 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic)
694 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical)
695
696 /*********************************************************
697 * Load higher 16 bits of the first word in GPR with imm  *
698 * Format:  OP rt, immediate                              *
699 *********************************************************/
700 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
701
702 /*********************************************************
703 * Move from HI/LO to GPR                                 *
704 * Format:  OP rd                                         *
705 *********************************************************/
706 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
707 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
708
709 static void mflohiCheckStall(void)
710 {
711         u32 left = psxRegs.muldivBusyCycle - psxRegs.cycle;
712         if (left <= 37) {
713                 //printf("muldiv stall %u\n", left);
714                 psxRegs.cycle = psxRegs.muldivBusyCycle;
715         }
716 }
717
718 void psxMFHI_stall() { mflohiCheckStall(); psxMFHI(); }
719 void psxMFLO_stall() { mflohiCheckStall(); psxMFLO(); }
720
721 /*********************************************************
722 * Move to GPR to HI/LO & Register jump                   *
723 * Format:  OP rs                                         *
724 *********************************************************/
725 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
726 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
727
728 /*********************************************************
729 * Special purpose instructions                           *
730 * Format:  OP                                            *
731 *********************************************************/
732 void psxBREAK() {
733         psxRegs.pc -= 4;
734         psxException(0x24, branch);
735 }
736
737 void psxSYSCALL() {
738         psxRegs.pc -= 4;
739         psxException(0x20, branch);
740 }
741
742 void psxRFE() {
743 //      SysPrintf("psxRFE\n");
744         psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
745                                                   ((psxRegs.CP0.n.Status & 0x3c) >> 2);
746         psxTestSWInts();
747 }
748
749 /*********************************************************
750 * Register branch logic                                  *
751 * Format:  OP rs, rt, offset                             *
752 *********************************************************/
753 #define RepBranchi32(op)      if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
754
755 void psxBEQ() { RepBranchi32(==) }  // Branch if Rs == Rt
756 void psxBNE() { RepBranchi32(!=) }  // Branch if Rs != Rt
757
758 /*********************************************************
759 * Jump to target                                         *
760 * Format:  OP target                                     *
761 *********************************************************/
762 void psxJ()   {               doBranch(_JumpTarget_); }
763 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
764
765 /*********************************************************
766 * Register jump                                          *
767 * Format:  OP rs, rd                                     *
768 *********************************************************/
769 void psxJR()   {
770         doBranch(_rRs_ & ~3);
771         psxJumpTest();
772 }
773
774 void psxJALR() {
775         u32 temp = _u32(_rRs_);
776         if (_Rd_) { _SetLink(_Rd_); }
777         doBranch(temp & ~3);
778 }
779
780 /*********************************************************
781 * Load and store for GPR                                 *
782 * Format:  OP rt, offset(base)                           *
783 *********************************************************/
784
785 #define _oB_ (_u32(_rRs_) + _Imm_)
786
787 void psxLB() {
788         if (_Rt_) {
789                 _i32(_rRt_) = (signed char)psxMemRead8(_oB_); 
790         } else {
791                 psxMemRead8(_oB_); 
792         }
793 }
794
795 void psxLBU() {
796         if (_Rt_) {
797                 _u32(_rRt_) = psxMemRead8(_oB_);
798         } else {
799                 psxMemRead8(_oB_); 
800         }
801 }
802
803 void psxLH() {
804         if (_Rt_) {
805                 _i32(_rRt_) = (short)psxMemRead16(_oB_);
806         } else {
807                 psxMemRead16(_oB_);
808         }
809 }
810
811 void psxLHU() {
812         if (_Rt_) {
813                 _u32(_rRt_) = psxMemRead16(_oB_);
814         } else {
815                 psxMemRead16(_oB_);
816         }
817 }
818
819 void psxLW() {
820         if (_Rt_) {
821                 _u32(_rRt_) = psxMemRead32(_oB_);
822         } else {
823                 psxMemRead32(_oB_);
824         }
825 }
826
827 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
828 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
829
830 void psxLWL() {
831         u32 addr = _oB_;
832         u32 shift = addr & 3;
833         u32 mem = psxMemRead32(addr & ~3);
834
835         if (!_Rt_) return;
836         _u32(_rRt_) =   ( _u32(_rRt_) & LWL_MASK[shift]) | 
837                                         ( mem << LWL_SHIFT[shift]);
838
839         /*
840         Mem = 1234.  Reg = abcd
841
842         0   4bcd   (mem << 24) | (reg & 0x00ffffff)
843         1   34cd   (mem << 16) | (reg & 0x0000ffff)
844         2   234d   (mem <<  8) | (reg & 0x000000ff)
845         3   1234   (mem      ) | (reg & 0x00000000)
846         */
847 }
848
849 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
850 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
851
852 void psxLWR() {
853         u32 addr = _oB_;
854         u32 shift = addr & 3;
855         u32 mem = psxMemRead32(addr & ~3);
856
857         if (!_Rt_) return;
858         _u32(_rRt_) =   ( _u32(_rRt_) & LWR_MASK[shift]) | 
859                                         ( mem >> LWR_SHIFT[shift]);
860
861         /*
862         Mem = 1234.  Reg = abcd
863
864         0   1234   (mem      ) | (reg & 0x00000000)
865         1   a123   (mem >>  8) | (reg & 0xff000000)
866         2   ab12   (mem >> 16) | (reg & 0xffff0000)
867         3   abc1   (mem >> 24) | (reg & 0xffffff00)
868         */
869 }
870
871 void psxSB() { psxMemWrite8 (_oB_, _rRt_ &   0xff); }
872 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
873 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
874
875 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
876 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
877
878 void psxSWL() {
879         u32 addr = _oB_;
880         u32 shift = addr & 3;
881         u32 mem = psxMemRead32(addr & ~3);
882
883         psxMemWrite32(addr & ~3,  (_u32(_rRt_) >> SWL_SHIFT[shift]) |
884                              (  mem & SWL_MASK[shift]) );
885         /*
886         Mem = 1234.  Reg = abcd
887
888         0   123a   (reg >> 24) | (mem & 0xffffff00)
889         1   12ab   (reg >> 16) | (mem & 0xffff0000)
890         2   1abc   (reg >>  8) | (mem & 0xff000000)
891         3   abcd   (reg      ) | (mem & 0x00000000)
892         */
893 }
894
895 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
896 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
897
898 void psxSWR() {
899         u32 addr = _oB_;
900         u32 shift = addr & 3;
901         u32 mem = psxMemRead32(addr & ~3);
902
903         psxMemWrite32(addr & ~3,  (_u32(_rRt_) << SWR_SHIFT[shift]) |
904                              (  mem & SWR_MASK[shift]) );
905
906         /*
907         Mem = 1234.  Reg = abcd
908
909         0   abcd   (reg      ) | (mem & 0x00000000)
910         1   bcd4   (reg <<  8) | (mem & 0x000000ff)
911         2   cd34   (reg << 16) | (mem & 0x0000ffff)
912         3   d234   (reg << 24) | (mem & 0x00ffffff)
913         */
914 }
915
916 /*********************************************************
917 * Moves between GPR and COPx                             *
918 * Format:  OP rt, fs                                     *
919 *********************************************************/
920 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
921 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
922
923 void psxTestSWInts() {
924         if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
925            psxRegs.CP0.n.Status & 0x1) {
926                 psxRegs.CP0.n.Cause &= ~0x7c;
927                 psxException(psxRegs.CP0.n.Cause, branch);
928         }
929 }
930
931 void MTC0(int reg, u32 val) {
932 //      SysPrintf("MTC0 %d: %x\n", reg, val);
933         switch (reg) {
934                 case 12: // Status
935                         psxRegs.CP0.r[12] = val;
936                         psxTestSWInts();
937                         break;
938
939                 case 13: // Cause
940                         psxRegs.CP0.n.Cause &= ~0x0300;
941                         psxRegs.CP0.n.Cause |= val & 0x0300;
942                         psxTestSWInts();
943                         break;
944
945                 default:
946                         psxRegs.CP0.r[reg] = val;
947                         break;
948         }
949 }
950
951 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
952 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
953
954 /*********************************************************
955 * Unknow instruction (would generate an exception)       *
956 * Format:  ?                                             *
957 *********************************************************/
958 void psxNULL() { 
959 #ifdef PSXCPU_LOG
960         PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
961 #endif
962 }
963
964 void psxSPECIAL() {
965         psxSPC[_Funct_]();
966 }
967
968 void psxREGIMM() {
969         psxREG[_Rt_]();
970 }
971
972 void psxCOP0() {
973         psxCP0[_Rs_]();
974 }
975
976 void psxCOP2() {
977         psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
978 }
979
980 void psxCOP2_stall() {
981         u32 f = _Funct_;
982         gteCheckStall(f);
983         psxCP2[f]((struct psxCP2Regs *)&psxRegs.CP2D);
984 }
985
986 void psxBASIC(struct psxCP2Regs *regs) {
987         psxCP2BSC[_Rs_]();
988 }
989
990 void psxHLE() {
991 //      psxHLEt[psxRegs.code & 0xffff]();
992 //      psxHLEt[psxRegs.code & 0x07]();         // HDHOSHY experimental patch
993     uint32_t hleCode = psxRegs.code & 0x03ffffff;
994     if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
995         psxNULL();
996     } else {
997         psxHLEt[hleCode]();
998     }
999 }
1000
1001 void (*psxBSC[64])() = {
1002         psxSPECIAL, psxREGIMM, psxJ   , psxJAL  , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
1003         psxADDI   , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
1004         psxCOP0   , psxNULL  , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1005         psxNULL   , psxNULL  , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1006         psxLB     , psxLH    , psxLWL , psxLW   , psxLBU , psxLHU , psxLWR , psxNULL,
1007         psxSB     , psxSH    , psxSWL , psxSW   , psxNULL, psxNULL, psxSWR , psxNULL, 
1008         psxNULL   , psxNULL  , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1009         psxNULL   , psxNULL  , gteSWC2, psxHLE  , psxNULL, psxNULL, psxNULL, psxNULL 
1010 };
1011
1012
1013 void (*psxSPC[64])() = {
1014         psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV   , psxNULL , psxSRLV, psxSRAV,
1015         psxJR  , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
1016         psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL   , psxNULL , psxNULL, psxNULL,
1017         psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL   , psxNULL , psxNULL, psxNULL,
1018         psxADD , psxADDU , psxSUB , psxSUBU, psxAND    , psxOR   , psxXOR , psxNOR ,
1019         psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL   , psxNULL , psxNULL, psxNULL,
1020         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL,
1021         psxNULL, psxNULL , psxNULL, psxNULL, psxNULL   , psxNULL , psxNULL, psxNULL
1022 };
1023
1024 void (*psxREG[32])() = {
1025         psxBLTZ  , psxBGEZ  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1026         psxNULL  , psxNULL  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1027         psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1028         psxNULL  , psxNULL  , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1029 };
1030
1031 void (*psxCP0[32])() = {
1032         psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
1033         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1034         psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1035         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1036 };
1037
1038 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
1039         psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
1040         psxNULL , psxNULL , psxNULL , psxNULL, gteOP  , psxNULL , psxNULL , psxNULL, // 08
1041         gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
1042         psxNULL , psxNULL , psxNULL , gteNCCS, gteCC  , psxNULL , gteNCS  , psxNULL, // 18
1043         gteNCT  , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
1044         gteSQR  , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28 
1045         gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
1046         psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF  , gteGPL  , gteNCCT  // 38
1047 };
1048
1049 void (*psxCP2BSC[32])() = {
1050         gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
1051         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1052         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1053         psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1054 };
1055
1056
1057 ///////////////////////////////////////////
1058
1059 static int intInit() {
1060         #ifdef ICACHE_EMULATION
1061         /* We have to allocate the icache memory even if 
1062          * the user has not enabled it as otherwise it can cause issues.
1063          */
1064         if (!ICache_Addr)
1065         {
1066                 ICache_Addr = malloc(0x1000);
1067                 if (!ICache_Addr)
1068                 {
1069                         return -1;
1070                 }
1071         }
1072
1073         if (!ICache_Code)
1074         {
1075                 ICache_Code = malloc(0x1000);
1076                 if (!ICache_Code)
1077                 {
1078                         return -1;
1079                 }
1080         }
1081         memset(ICache_Addr, 0xff, 0x1000);
1082         memset(ICache_Code, 0xff, 0x1000);
1083         #endif
1084         return 0;
1085 }
1086
1087 static void intReset() {
1088         #ifdef ICACHE_EMULATION
1089         memset(ICache_Addr, 0xff, 0x1000);
1090         memset(ICache_Code, 0xff, 0x1000);
1091         #endif
1092 }
1093
1094 void intExecute() {
1095         extern int stop;
1096         for (;!stop;) 
1097                 execI();
1098 }
1099
1100 void intExecuteBlock() {
1101         branch2 = 0;
1102         while (!branch2) execI();
1103 }
1104
1105 static void intClear(u32 Addr, u32 Size) {
1106 }
1107
1108 void intNotify (int note, void *data) {
1109         #ifdef ICACHE_EMULATION
1110         /* Gameblabla - Only clear the icache if it's isolated */
1111         if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED)
1112         {
1113                 memset(ICache_Addr, 0xff, 0x1000);
1114                 memset(ICache_Code, 0xff, 0x1000);
1115         }
1116         #endif
1117 }
1118
1119 void applyConfig() {
1120         assert(psxBSC[18] == psxCOP2  || psxBSC[18] == psxCOP2_stall);
1121         assert(psxBSC[50] == gteLWC2  || psxBSC[50] == gteLWC2_stall);
1122         assert(psxBSC[58] == gteSWC2  || psxBSC[58] == gteSWC2_stall);
1123         assert(psxSPC[16] == psxMFHI  || psxSPC[16] == psxMFHI_stall);
1124         assert(psxSPC[18] == psxMFLO  || psxSPC[18] == psxMFLO_stall);
1125         assert(psxSPC[24] == psxMULT  || psxSPC[24] == psxMULT_stall);
1126         assert(psxSPC[25] == psxMULTU || psxSPC[25] == psxMULTU_stall);
1127         assert(psxSPC[26] == psxDIV   || psxSPC[26] == psxDIV_stall);
1128         assert(psxSPC[27] == psxDIVU  || psxSPC[27] == psxDIVU_stall);
1129
1130         if (Config.DisableStalls) {
1131                 psxBSC[18] = psxCOP2;
1132                 psxBSC[50] = gteLWC2;
1133                 psxBSC[58] = gteSWC2;
1134                 psxSPC[16] = psxMFHI;
1135                 psxSPC[18] = psxMFLO;
1136                 psxSPC[24] = psxMULT;
1137                 psxSPC[25] = psxMULTU;
1138                 psxSPC[26] = psxDIV;
1139                 psxSPC[27] = psxDIVU;
1140         } else {
1141                 psxBSC[18] = psxCOP2_stall;
1142                 psxBSC[50] = gteLWC2_stall;
1143                 psxBSC[58] = gteSWC2_stall;
1144                 psxSPC[16] = psxMFHI_stall;
1145                 psxSPC[18] = psxMFLO_stall;
1146                 psxSPC[24] = psxMULT_stall;
1147                 psxSPC[25] = psxMULTU_stall;
1148                 psxSPC[26] = psxDIV_stall;
1149                 psxSPC[27] = psxDIVU_stall;
1150         }
1151 }
1152
1153 static void intShutdown() {
1154         #ifdef ICACHE_EMULATION
1155         if (ICache_Addr)
1156         {
1157                 free(ICache_Addr);
1158                 ICache_Addr = NULL;
1159         }
1160
1161         if (ICache_Code)
1162         {
1163                 free(ICache_Code);
1164                 ICache_Code = NULL;
1165         }
1166         #endif
1167 }
1168
1169 // interpreter execution
1170 void execI() {
1171         u32 *code;
1172         #ifdef ICACHE_EMULATION
1173         if (Config.icache_emulation)
1174         {
1175                 code = Read_ICache(psxRegs.pc);
1176         }
1177         else
1178         #endif
1179         {
1180                 code = (u32 *)PSXM(psxRegs.pc);
1181         }
1182         psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
1183
1184         debugI();
1185
1186         if (Config.Debug) ProcessDebug();
1187
1188         psxRegs.pc += 4;
1189         psxRegs.cycle += BIAS;
1190
1191         psxBSC[psxRegs.code >> 26]();
1192 }
1193
1194 R3000Acpu psxInt = {
1195         intInit,
1196         intReset,
1197         intExecute,
1198         intExecuteBlock,
1199         intClear,
1200 #ifdef ICACHE_EMULATION
1201         intNotify,
1202 #endif
1203         applyConfig,
1204         intShutdown
1205 };