OSDN Git Service

Merge branch 'master' of github.com:Artanejp/common_source_project-fm7
[csp-qt/common_source_project-fm7.git] / source / src / vm / libcpu_newdev / libcpu_i386 / i386op16_real.cpp
1
2 #include "../vm.h"
3 #include "../../emu.h"
4 #include "./i386_real.h"
5
6 #ifdef I386_PSEUDO_BIOS
7 #define BIOS_INT(num) if(cpustate->bios != NULL) { \
8         uint16_t regs[8], sregs[4]; \
9         regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
10         regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
11         sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
12         sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
13         int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
14         if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag)) { \
15                 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
16                 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
17                 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
18                 return; \
19         } \
20 }
21 #define BIOS_CALL(address) if(cpustate->bios != NULL) { \
22         uint16_t regs[8], sregs[4]; \
23         regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
24         regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
25         sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
26         sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
27         int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \
28         if(cpustate->bios->bios_call_i86(address, regs, sregs, &ZeroFlag, &CarryFlag)) { \
29                 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
30                 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
31                 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
32                 return; \
33         } \
34 }
35 #endif
36
37 void I386_OPS::i386_call_abs16()        // Opcode 0x9a
38 {
39         UINT16 offset = FETCH16();
40         UINT16 ptr = FETCH16();
41 #ifdef I386_PSEUDO_BIOS
42         BIOS_CALL(((ptr << 4) + offset) & cpustate->a20_mask)
43 #endif
44                 //printf(" \n");
45
46         if( PROTECTED_MODE && !V8086_MODE)
47         {
48                 i386_protected_mode_call(ptr,offset,0,0);
49         }
50         else
51         {
52                 PUSH16( cpustate->sreg[CS].selector );
53                 PUSH16( cpustate->eip );
54                 cpustate->sreg[CS].selector = ptr;
55                 cpustate->performed_intersegment_jump = 1;
56                 cpustate->eip = offset;
57                 i386_load_segment_descriptor(CS);
58         }
59         CYCLES(CYCLES_CALL_INTERSEG);      /* TODO: Timing = 17 + m */
60         CHANGE_PC(cpustate->eip);
61 }
62
63 void I386_OPS::i386_call_rel16()        // Opcode 0xe8
64 {
65         INT16 disp = FETCH16();
66
67 #ifdef I386_PSEUDO_BIOS
68         BIOS_CALL((cpustate->pc + disp) & cpustate->a20_mask)
69 #endif
70
71         PUSH16( cpustate->eip );
72         if (cpustate->sreg[CS].d)
73         {
74                 cpustate->eip += disp;
75         }
76         else
77         {
78                 cpustate->eip = (cpustate->eip + disp) & 0xffff;
79         }
80         CHANGE_PC(cpustate->eip);
81         CYCLES(CYCLES_CALL);       /* TODO: Timing = 7 + m */
82 }
83
84 void I386_OPS::i386_groupFF_16()        // Opcode 0xff
85 {
86         UINT8 modrm = FETCH();
87
88         switch( (modrm >> 3) & 0x7 )
89         {
90                 case 0:         /* INC Rm16 */
91                         if( modrm >= 0xc0 ) {
92                                 UINT16 dst = LOAD_RM16(modrm);
93                                 dst = INC16(dst);
94                                 STORE_RM16(modrm, dst);
95                                 CYCLES(CYCLES_INC_REG);
96                         } else {
97                                 UINT32 ea = GetEA(modrm,1);
98                                 UINT16 dst = READ16(ea);
99                                 dst = INC16(dst);
100                                 WRITE16(ea, dst);
101                                 CYCLES(CYCLES_INC_MEM);
102                         }
103                         break;
104                 case 1:         /* DEC Rm16 */
105                         if( modrm >= 0xc0 ) {
106                                 UINT16 dst = LOAD_RM16(modrm);
107                                 dst = DEC16(dst);
108                                 STORE_RM16(modrm, dst);
109                                 CYCLES(CYCLES_DEC_REG);
110                         } else {
111                                 UINT32 ea = GetEA(modrm,1);
112                                 UINT16 dst = READ16(ea);
113                                 dst = DEC16(dst);
114                                 WRITE16(ea, dst);
115                                 CYCLES(CYCLES_DEC_MEM);
116                         }
117                         break;
118                 case 2:         /* CALL Rm16 */
119                         {
120                                 UINT16 address;
121                                 if( modrm >= 0xc0 ) {
122                                         address = LOAD_RM16(modrm);
123                                         CYCLES(CYCLES_CALL_REG);       /* TODO: Timing = 7 + m */
124                                 } else {
125                                         UINT32 ea = GetEA(modrm,0);
126                                         address = READ16(ea);
127                                         CYCLES(CYCLES_CALL_MEM);       /* TODO: Timing = 10 + m */
128                                 }
129 #ifdef I386_PSEUDO_BIOS
130                                 BIOS_CALL(((cpustate->sreg[CS].selector << 4) + address) & cpustate->a20_mask)
131 #endif
132                                 PUSH16( cpustate->eip );
133                                 cpustate->eip = address;
134                                 CHANGE_PC(cpustate->eip);
135                         }
136                         break;
137                 case 3:         /* CALL FAR Rm16 */
138                         {
139                                 UINT16 address, selector;
140                                 if( modrm >= 0xc0 )
141                                 {
142                                         report_invalid_modrm( "groupFF_16", modrm);
143                                 }
144                                 else
145                                 {
146                                         UINT32 ea = GetEA(modrm,0);
147                                         address = READ16(ea + 0);
148                                         selector = READ16(ea + 2);
149                                         CYCLES(CYCLES_CALL_MEM_INTERSEG);      /* TODO: Timing = 10 + m */
150 #ifdef I386_PSEUDO_BIOS
151                                         BIOS_CALL(((selector << 4) + address) & cpustate->a20_mask)
152 #endif
153                                         if(PROTECTED_MODE && !V8086_MODE)
154                                         {
155                                                 i386_protected_mode_call(selector,address,1,0);
156                                         }
157                                         else
158                                         {
159                                                 PUSH16( cpustate->sreg[CS].selector );
160                                                 PUSH16( cpustate->eip );
161                                                 cpustate->sreg[CS].selector = selector;
162                                                 cpustate->performed_intersegment_jump = 1;
163                                                 i386_load_segment_descriptor( CS );
164                                                 cpustate->eip = address;
165                                                 CHANGE_PC(cpustate->eip);
166                                         }
167                                 }
168                         }
169                         break;
170                 case 4:         /* JMP Rm16 */
171                         {
172                                 UINT16 address;
173                                 if( modrm >= 0xc0 ) {
174                                         address = LOAD_RM16(modrm);
175                                         CYCLES(CYCLES_JMP_REG);        /* TODO: Timing = 7 + m */
176                                 } else {
177                                         UINT32 ea = GetEA(modrm,0);
178                                         address = READ16(ea);
179                                         CYCLES(CYCLES_JMP_MEM);        /* TODO: Timing = 10 + m */
180                                 }
181                                 cpustate->eip = address;
182                                 CHANGE_PC(cpustate->eip);
183                         }
184                         break;
185                 case 5:         /* JMP FAR Rm16 */
186                         {
187                                 UINT16 address, selector;
188
189                                 if( modrm >= 0xc0 )
190                                 {
191                                         report_invalid_modrm( "groupFF_16", modrm);
192                                 }
193                                 else
194                                 {
195                                         UINT32 ea = GetEA(modrm,0);
196                                         address = READ16(ea + 0);
197                                         selector = READ16(ea + 2);
198                                         CYCLES(CYCLES_JMP_MEM_INTERSEG);       /* TODO: Timing = 10 + m */
199                                         if(PROTECTED_MODE && !V8086_MODE)
200                                         {
201                                                 i386_protected_mode_jump(selector,address,1,0);
202                                         }
203                                         else
204                                         {
205                                                 cpustate->sreg[CS].selector = selector;
206                                                 cpustate->performed_intersegment_jump = 1;
207                                                 i386_load_segment_descriptor( CS );
208                                                 cpustate->eip = address;
209                                                 CHANGE_PC(cpustate->eip);
210                                         }
211                                 }
212                         }
213                         break;
214                 case 6:         /* PUSH Rm16 */
215                         {
216                                 UINT16 value;
217                                 if( modrm >= 0xc0 ) {
218                                         value = LOAD_RM16(modrm);
219                                 } else {
220                                         UINT32 ea = GetEA(modrm,0);
221                                         value = READ16(ea);
222                                 }
223                                 PUSH16(value);
224                                 CYCLES(CYCLES_PUSH_RM);
225                         }
226                         break;
227                 default:
228                         report_invalid_modrm( "groupFF_16", modrm);
229                         break;
230         }
231 }