comparison ztestgen.c @ 617:33ff0171301b

Added support for JP in Z80 test generator
author Michael Pavone <pavone@retrodev.com>
date Mon, 29 Dec 2014 20:56:05 -0800
parents b7b7a1cab44a
children abc834e4a520
comparison
equal deleted inserted replaced
616:649db9397fa1 617:33ff0171301b
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) {
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 cur = ld_ir16(cur, reg, reg_values[reg]);
298 } 335 }
336 }
337
338 if (inst->op == Z80_JP && addr_mode == Z80_REG_INDIRECT) {
339 uint16_t address = cur - prog + (inst->ea_reg == Z80_HL ? 3 : 4) + instlen + 1;
340 cur = ld_ir16(cur, inst->ea_reg, address);
299 } 341 }
300 342
301 //copy instruction 343 //copy instruction
302 if (instlen == 3) { 344 if (instlen == 3) {
303 memcpy(cur, instbuf, 2); 345 memcpy(cur, instbuf, 2);
308 } 350 }
309 351
310 //immed/displacement byte(s) 352 //immed/displacement byte(s)
311 if (addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE) { 353 if (addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE) {
312 *(cur++) = inst->ea_reg; 354 *(cur++) = inst->ea_reg;
355 } else if (inst->op == Z80_JP && addr_mode == Z80_IMMED) {
356 uint16_t address = cur - prog + 5; //2 for immed address, 3 for instruction to skip
357 *(cur++) = address;
358 *(cur++) = address >> 8;
359 cur = ld_ir16(cur, Z80_HL, 0xDEAD);
313 } else if (addr_mode == Z80_IMMED & inst->op != Z80_IM) { 360 } else if (addr_mode == Z80_IMMED & inst->op != Z80_IM) {
314 *(cur++) = inst->immed & 0xFF; 361 *(cur++) = inst->immed & 0xFF;
315 if (word_sized) { 362 if (word_sized) {
316 *(cur++) = inst->immed >> 8; 363 *(cur++) = inst->immed >> 8;
317 } 364 }
322 if (inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET) { 369 if (inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET) {
323 *(cur++) = inst->immed & 0xFF; 370 *(cur++) = inst->immed & 0xFF;
324 } 371 }
325 if (instlen == 3) { 372 if (instlen == 3) {
326 *(cur++) = instbuf[2]; 373 *(cur++) = instbuf[2];
374 }
375 if (inst->op == Z80_JP && addr_mode == Z80_REG_INDIRECT) {
376 cur = inc_r(cur, counter_reg);
327 } 377 }
328 if (!i) { 378 if (!i) {
329 //Save AF from first run 379 //Save AF from first run
330 cur = push(cur, Z80_AF); 380 cur = push(cur, Z80_AF);
331 if (is_mem) { 381 if (is_mem) {
397 } 447 }
398 448
399 449
400 uint8_t should_skip(z80inst * inst) 450 uint8_t should_skip(z80inst * inst)
401 { 451 {
402 return inst->op >= Z80_JP || (inst->op >= Z80_LDI && inst->op <= Z80_CPDR) || inst->op == Z80_HALT 452 return inst->op >= Z80_JPCC || (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 453 || 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; 454 || inst->op == Z80_DI || inst->op == Z80_EI;
405 } 455 }
406 456
407 void z80_gen_all() 457 void z80_gen_all()