Mercurial > repos > blastem
comparison ztestgen.c @ 744:fc68992cf18d
Merge windows branch with latest changes
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 May 2015 21:19:55 -0700 |
parents | 3072fb746601 |
children | a6c6b621d0dc |
comparison
equal
deleted
inserted
replaced
743:cf78cb045fa4 | 744:fc68992cf18d |
---|---|
22 extern char *z80_mnemonics[Z80_OTDR+1]; | 22 extern char *z80_mnemonics[Z80_OTDR+1]; |
23 extern char * z80_regs[Z80_USE_IMMED]; | 23 extern char * z80_regs[Z80_USE_IMMED]; |
24 #define PRE_IX 0xDD | 24 #define PRE_IX 0xDD |
25 #define PRE_IY 0xFD | 25 #define PRE_IY 0xFD |
26 #define LD_IR16 0x01 | 26 #define LD_IR16 0x01 |
27 #define INC_R8 0x04 | |
27 #define LD_IR8 0x06 | 28 #define LD_IR8 0x06 |
28 #define LD_RR8 0x40 | 29 #define LD_RR8 0x40 |
29 #define AND_R 0xA0 | 30 #define AND_R 0xA0 |
30 #define PUSH 0xC5 | 31 #define PUSH 0xC5 |
31 #define POP 0xC1 | 32 #define POP 0xC1 |
139 reg = (reg - Z80_C) ^ 1; | 140 reg = (reg - Z80_C) ^ 1; |
140 } | 141 } |
141 *(dst++) = AND_R | reg; | 142 *(dst++) = AND_R | reg; |
142 return dst; | 143 return dst; |
143 } | 144 } |
145 } | |
146 | |
147 uint8_t * inc_r(uint8_t *dst, uint8_t reg) | |
148 { | |
149 if (reg == Z80_IXH || reg == Z80_IXL) { | |
150 *(dst++) = PRE_IX; | |
151 return inc_r(dst, reg - (Z80_IXL - Z80_L)); | |
152 } else if(reg == Z80_IYH || reg == Z80_IYL) { | |
153 *(dst++) = PRE_IY; | |
154 return inc_r(dst, reg - (Z80_IYL - Z80_L)); | |
155 } else { | |
156 *(dst++) = INC_R8 | reg << 3; | |
157 return dst; | |
158 } | |
159 } | |
160 | |
161 void mark_used8(uint8_t *reg_usage, uint16_t *reg_values, uint8_t reg, uint8_t init_value) | |
162 { | |
163 reg_usage[reg] = 1; | |
164 reg_values[reg] = init_value; | |
165 uint8_t word_reg = z80_word_reg(reg); | |
166 if (word_reg != Z80_UNUSED) { | |
167 reg_usage[word_reg] = 1; | |
168 reg_values[word_reg] = (reg_values[z80_high_reg(word_reg)] << 8) | (reg_values[z80_low_reg(word_reg)] & 0xFF); | |
169 } | |
170 } | |
171 | |
172 uint8_t alloc_reg8(uint8_t *reg_usage, uint16_t *reg_values, uint8_t init_value) | |
173 { | |
174 for (uint8_t reg = 0; reg < Z80_BC; reg++) | |
175 { | |
176 if (!reg_usage[reg]) { | |
177 mark_used8(reg_usage, reg_values, reg, init_value); | |
178 return reg; | |
179 } | |
180 } | |
181 return Z80_UNUSED; | |
144 } | 182 } |
145 | 183 |
146 void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) | 184 void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen) |
147 { | 185 { |
148 z80inst copy; | 186 z80inst copy; |
182 reg_values[z80_high_reg(inst->ea_reg)] = reg_values[inst->ea_reg] >> 8; | 220 reg_values[z80_high_reg(inst->ea_reg)] = reg_values[inst->ea_reg] >> 8; |
183 reg_usage[z80_high_reg(inst->ea_reg)] = 1; | 221 reg_usage[z80_high_reg(inst->ea_reg)] = 1; |
184 reg_values[z80_low_reg(inst->ea_reg)] = reg_values[inst->ea_reg] & 0xFF; | 222 reg_values[z80_low_reg(inst->ea_reg)] = reg_values[inst->ea_reg] & 0xFF; |
185 reg_usage[z80_low_reg(inst->ea_reg)] = 1; | 223 reg_usage[z80_low_reg(inst->ea_reg)] = 1; |
186 } else { | 224 } else { |
187 reg_values[inst->ea_reg] = rand() % 256; | 225 mark_used8(reg_usage, reg_values, inst->ea_reg, rand() % 256); |
188 uint8_t word_reg = z80_word_reg(inst->ea_reg); | |
189 if (word_reg != Z80_UNUSED) { | |
190 reg_usage[word_reg] = 1; | |
191 reg_values[word_reg] = (reg_values[z80_high_reg(word_reg)] << 8) | (reg_values[z80_low_reg(word_reg)] & 0xFF); | |
192 } | |
193 } | 226 } |
194 break; | 227 break; |
195 case Z80_REG_INDIRECT: | 228 case Z80_REG_INDIRECT: |
196 is_mem = 1; | 229 is_mem = 1; |
197 reg_values[inst->ea_reg] = 0x1000 + (rand() % 256 - 128); | 230 reg_values[inst->ea_reg] = 0x1000 + (rand() % 256 - 128); |
253 } | 286 } |
254 } | 287 } |
255 } | 288 } |
256 reg_usage[inst->reg] = 1; | 289 reg_usage[inst->reg] = 1; |
257 } | 290 } |
291 uint8_t counter_reg = Z80_UNUSED; | |
292 if (inst->op >= Z80_JP && inst->op <= Z80_JRCC) { | |
293 counter_reg = alloc_reg8(reg_usage, reg_values, 0); | |
294 } | |
258 puts("--------------"); | 295 puts("--------------"); |
259 for (uint8_t reg = 0; reg < Z80_UNUSED; reg++) { | 296 for (uint8_t reg = 0; reg < Z80_UNUSED; reg++) { |
260 if (reg_values[reg]) { | 297 if (reg_values[reg]) { |
261 printf("%s: %X\n", z80_regs[reg], reg_values[reg]); | 298 printf("%s: %X\n", z80_regs[reg], reg_values[reg]); |
262 } | 299 } |
291 cur = push(cur, Z80_BC); | 328 cur = push(cur, Z80_BC); |
292 cur = pop(cur, Z80_AF); | 329 cur = pop(cur, Z80_AF); |
293 | 330 |
294 //setup other regs | 331 //setup other regs |
295 for (uint8_t reg = Z80_BC; reg <= Z80_IY; reg++) { | 332 for (uint8_t reg = Z80_BC; reg <= Z80_IY; reg++) { |
296 if (reg != Z80_AF && reg != Z80_SP) { | 333 if (reg != Z80_AF && reg != Z80_SP && (inst->op != Z80_JP || addr_mode != Z80_REG_INDIRECT || inst->ea_reg != reg)) { |
297 cur = ld_ir16(cur, reg, reg_values[reg]); | 334 if (i == 1 && (z80_high_reg(reg) == counter_reg || z80_low_reg(reg) == counter_reg)) { |
298 } | 335 if (z80_high_reg(reg) == counter_reg) { |
336 if (reg_usage[z80_low_reg(reg)]) { | |
337 cur = ld_ir8(cur, z80_low_reg(reg), reg_values[z80_low_reg(reg)]); | |
338 } | |
339 } else if (reg_usage[z80_high_reg(reg)]) { | |
340 cur = ld_ir8(cur, z80_high_reg(reg), reg_values[z80_high_reg(reg)]); | |
341 } | |
342 } else { | |
343 cur = ld_ir16(cur, reg, reg_values[reg]); | |
344 } | |
345 } | |
346 } | |
347 | |
348 if (inst->op == Z80_JP && addr_mode == Z80_REG_INDIRECT) { | |
349 uint16_t address = cur - prog + (inst->ea_reg == Z80_HL ? 3 : 4) + instlen + 1 + i; | |
350 cur = ld_ir16(cur, inst->ea_reg, address); | |
299 } | 351 } |
300 | 352 |
301 //copy instruction | 353 //copy instruction |
302 if (instlen == 3) { | 354 if (instlen == 3) { |
303 memcpy(cur, instbuf, 2); | 355 memcpy(cur, instbuf, 2); |
308 } | 360 } |
309 | 361 |
310 //immed/displacement byte(s) | 362 //immed/displacement byte(s) |
311 if (addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE) { | 363 if (addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE) { |
312 *(cur++) = inst->ea_reg; | 364 *(cur++) = inst->ea_reg; |
365 } else if ((inst->op == Z80_JP || inst->op == Z80_JPCC) && addr_mode == Z80_IMMED) { | |
366 uint16_t address = cur - prog + 3 + i; //2 for immed address, 1/2 for instruction(s) to skip | |
367 *(cur++) = address; | |
368 *(cur++) = address >> 8; | |
369 } else if(inst->op == Z80_JR || inst->op == Z80_JRCC) { | |
370 *(cur++) = 1 + i; //skip one or 2 instructions based on value of i | |
313 } else if (addr_mode == Z80_IMMED & inst->op != Z80_IM) { | 371 } else if (addr_mode == Z80_IMMED & inst->op != Z80_IM) { |
314 *(cur++) = inst->immed & 0xFF; | 372 *(cur++) = inst->immed & 0xFF; |
315 if (word_sized) { | 373 if (word_sized) { |
316 *(cur++) = inst->immed >> 8; | 374 *(cur++) = inst->immed >> 8; |
317 } | 375 } |
322 if (inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET) { | 380 if (inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET) { |
323 *(cur++) = inst->immed & 0xFF; | 381 *(cur++) = inst->immed & 0xFF; |
324 } | 382 } |
325 if (instlen == 3) { | 383 if (instlen == 3) { |
326 *(cur++) = instbuf[2]; | 384 *(cur++) = instbuf[2]; |
385 } | |
386 if (inst->op >= Z80_JP && inst->op <= Z80_JRCC) { | |
387 cur = inc_r(cur, counter_reg); | |
388 if (i) { | |
389 //inc twice on second iteration so we can differentiate the two | |
390 cur = inc_r(cur, counter_reg); | |
391 } | |
327 } | 392 } |
328 if (!i) { | 393 if (!i) { |
329 //Save AF from first run | 394 //Save AF from first run |
330 cur = push(cur, Z80_AF); | 395 cur = push(cur, Z80_AF); |
331 if (is_mem) { | 396 if (is_mem) { |
397 } | 462 } |
398 | 463 |
399 | 464 |
400 uint8_t should_skip(z80inst * inst) | 465 uint8_t should_skip(z80inst * inst) |
401 { | 466 { |
402 return inst->op >= Z80_JP || (inst->op >= Z80_LDI && inst->op <= Z80_CPDR) || inst->op == Z80_HALT | 467 return inst->op >= Z80_DJNZ || (inst->op >= Z80_LDI && inst->op <= Z80_CPDR) || inst->op == Z80_HALT |
403 || inst->op == Z80_DAA || inst->op == Z80_RLD || inst->op == Z80_RRD || inst->op == Z80_NOP | 468 || inst->op == Z80_DAA || inst->op == Z80_RLD || inst->op == Z80_RRD || inst->op == Z80_NOP |
404 || inst->op == Z80_DI || inst->op == Z80_EI; | 469 || inst->op == Z80_DI || inst->op == Z80_EI; |
405 } | 470 } |
406 | 471 |
407 void z80_gen_all() | 472 void z80_gen_all() |